我有一个CustomMarkupExtension
课程。 Binding正在运行(!= null),但BindingExpressionBase
始终是null
。
有人可以解释我为什么吗?我需要让BindingExpressionBase
调用UpdateTarget()
方法。
public class CustomMarkupExtension : MarkupExtension
{
public BindingBase Binding { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (Binding == null) return null;
BindingExpressionBase expression = Binding.ProvideValue(serviceProvider) as BindingExpressionBase;
if (expression != null)
{
expression.UpdateTarget();
}
return expression;
}
}
<DataGrid ItemsSource="{Binding Path=Alarms, RelativeSource={RelativeSource TemplatedParent}}">
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Extensions:CustomMarkupExtension Binding={Binding Number}}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
答案 0 :(得分:1)
原因是您在模板中使用了标记扩展(在本例中为DataTemplate
)。当您的标记扩展由xaml解析器解析时 - 尚未创建控件,并且没有绑定目标。在这种情况下,您应该返回自己的标记扩展(return this
)。如果你这样做 - 每次使用该模板创建控件时都会再次应用它。
内置Binding
当然也遵循这种模式,这就是当目标对象尚不可用时它返回自身(Binding
)而不是BindingExpression
的原因。所以要修复,你必须这样做:
public class CustomMarkupExtension : MarkupExtension
{
public BindingBase Binding { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider) {
if (Binding == null) return null;
var result = Binding.ProvideValue(serviceProvider);
var expression = result as BindingExpressionBase;
if (expression != null) {
expression.UpdateTarget();
return expression;
}
// no expression - return self to apply it again later
return this;
}
}
如果您要创建不依赖于其他扩展的自定义标记扩展(在本例中为Binding
),您可以通过执行此操作来检查您是否有目标:
var target = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));
bool hasTarget = target.TargetObject is DependencyObject;