正如其他人所说,请首先考虑使用
ValueConverter来操作绑定。这是处理绑定的正确方法。
但是,如果您仍然想要使用MarkupExtension来绑定视图模型或数据上下文,那么您可以在MarkupExtension类中手动创建绑定。这类似于@nicolay.anykienko所采取的方法,但我们不需要创建附加属性。
例如,我创建了一个货币符号Markup Extension。默认行为是使用,但是一些视图模型具有其自己的CultureInfo属性,与当前文化不同。因此,对于这些视图模型,XAML需要绑定到此属性。请注意,这可以很容易地通过转换器完成,但出于示例的目的,这里是MarkupExtension:
public class CurrencySymbolExtension : MarkupExtension
{
public override object ProvideValue(IServiceProvider serviceProvider)
{
var targetProvider = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));
var targetElement = targetProvider.TargetObject as FrameworkElement;
var targetProperty = targetProvider.TargetProperty as DependencyProperty;
if (!String.IsNullOrEmpty(CultureBindingPath) &&
targetElement != null &&
targetProperty != null)
{
targetElement.DataContextChanged +=
(sender, args) => ApplyBinding(targetElement, targetProperty, args.NewValue);
var binding = ApplyBinding(targetElement, targetProperty, targetElement.DataContext);
return binding.ProvideValue(serviceProvider);
}
else
{
return CultureInfo.CurrentCulture.NumberFormat.CurrencySymbol;
}
}
private Binding ApplyBinding(DependencyObject target, DependencyProperty property, object source)
{
BindingOperations.ClearBinding(target, property);
var binding = new Binding(CultureBindingPath + ".NumberFormat.CurrencySymbol")
{
Mode = BindingMode.OneWay,
Source = source,
FallbackValue = CultureInfo.CurrentCulture.NumberFormat.CurrencySymbol,
};
BindingOperations.SetBinding(target, property, binding);
return binding;
}
public string CultureBindingPath { get; set; }
}
这随后会被用于以下方式:
<!-- Standard Usage -->
<TextBlock Text="{local:CurrencySymbol}"/>
<!-- With DataContext Binding -->
<TextBlock Text="{local:CurrencySymbol CultureBindingPath=ViewModelCulture}"/>
这里的ViewModelCulture
是视图模型上用作绑定源的属性。