正如其他人所说,请首先考虑使用ValueConverter。这是操作绑定的正确方法。
但是,如果您仍然想使用 MarkupExtension 绑定到视图模型或数据上下文,那么您可以在标记扩展类中手动创建绑定。这类似于@nicolay.anykienko 采用的方法,但我们不需要创建附加属性。
例如,我创建了一个货币符号标记扩展。默认行为是使用CultureInfo.CurrentCulture
但少数视图模型具有自己的 CultureInfo 属性,这些属性与当前文化不同。因此,对于这些视图模型,XAML 需要绑定到此属性。请注意,这可以使用 Converter 轻松完成,但为了举例,这里是标记扩展:
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)
{
// make sure that if the binding context changes then the binding gets updated.
targetElement.DataContextChanged +=
(sender, args) => ApplyBinding(targetElement, targetProperty, args.NewValue);
// apply a binding to the target
var binding = ApplyBinding(targetElement, targetProperty, targetElement.DataContext);
// return the initial value of the property
return binding.ProvideValue(serviceProvider);
}
else
{
// if no culture binding is provided then use the current culture
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
用作绑定的源。