BindingExpressionBase 在自定义 MarkupExtension 中为 null
BindingExpressionBase is null in custom MarkupExtension
我有一个CustomMarkupExtension
class。绑定正在工作(!= null),但 BindingExpressionBase
始终是 null
.
谁能解释一下为什么?我需要获取 BindingExpressionBase
来调用 UpdateTarget()
方法。
C# 代码
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;
}
}
XAML代码
<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>
原因是您在模板中使用标记扩展(在本例中为 DataTemplate
)。当您的标记扩展被 xaml 解析器解析时 - 尚未创建控件并且没有绑定目标。在这种情况下,您应该 return 您的标记扩展本身 (return this
)。如果您这样做 - 每次使用该模板创建控件时都会再次应用它。
内置 Binding
当然也遵循这种模式,这就是为什么当目标对象是 return 本身 (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;
我有一个CustomMarkupExtension
class。绑定正在工作(!= null),但 BindingExpressionBase
始终是 null
.
谁能解释一下为什么?我需要获取 BindingExpressionBase
来调用 UpdateTarget()
方法。
C# 代码
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;
}
}
XAML代码
<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>
原因是您在模板中使用标记扩展(在本例中为 DataTemplate
)。当您的标记扩展被 xaml 解析器解析时 - 尚未创建控件并且没有绑定目标。在这种情况下,您应该 return 您的标记扩展本身 (return this
)。如果您这样做 - 每次使用该模板创建控件时都会再次应用它。
内置 Binding
当然也遵循这种模式,这就是为什么当目标对象是 return 本身 (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;