WPF中绑定抽象类不同实现类的额外属性如何避免绑定失败
问题根源
绑定失败的核心原因是WPF DataGrid的UI虚拟化机制:滚动时,DataGrid会复用已加载的UI控件来显示新的数据源项。当原本绑定UtilityNaturalGasConsumptionModel的TextBlock被复用来显示UtilityElectricityConsumptionModel对象时,TextBlock的Text绑定会尝试访问不存在的ConversionCoefficient属性,从而触发绑定错误。
解决方案
以下三种方法可彻底解决这类绑定失败问题:
1. 给绑定添加FallbackValue和TargetNullValue
这是最快捷的修复方式,直接在绑定中指定属性不存在或为null时的默认值,避免绑定报错:
<Setter Property="Text" Value="{Binding ConversionCoefficient, StringFormat='0.00', FallbackValue='', TargetNullValue=''}" />
无需修改后端代码,仅调整XAML绑定即可生效。
2. 按数据类型匹配专属DataTemplate
通过为不同子类指定独立的DataTemplate,让非天然气类型的项根本不会尝试绑定ConversionCoefficient属性,从根源上避免跨类型绑定问题:
<DataGridTemplateColumn Width="100" Header="Conversion Coefficient"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <ContentControl> <ContentControl.Style> <Style TargetType="ContentControl"> <!-- 默认模板:适配非天然气类型 --> <Setter Property="ContentTemplate"> <Setter.Value> <DataTemplate> <TextBlock HorizontalAlignment="Stretch" Background="{StaticResource PrimarySolidColorBrush}" /> </DataTemplate> </Setter.Value> </Setter> <!-- 天然气类型专属模板 --> <Style.Triggers> <DataTrigger Binding="{Binding Source}" Value="{x:Static models:UtilitySource.NaturalGas}"> <Setter Property="ContentTemplate"> <Setter.Value> <DataTemplate DataType="{x:Type models:UtilityNaturalGasConsumptionModel}"> <TextBlock Padding="2,0,2,0" HorizontalAlignment="Right" Background="Transparent" Text="{Binding ConversionCoefficient, StringFormat='0.00'}" /> </DataTemplate> </Setter.Value> </Setter> </DataTrigger> </Style.Triggers> </Style> </ContentControl.Style> </ContentControl> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn>
3. 在抽象类中添加虚拟属性
在父类UtilityConsumptionModel中定义虚拟的ConversionCoefficient属性,子类按需重写:
public abstract class UtilityConsumptionModel { // 原有属性... public virtual double? ConversionCoefficient => null; } public class UtilityNaturalGasConsumptionModel : UtilityConsumptionModel { private double _conversionCoefficient; public override double? ConversionCoefficient { get => _conversionCoefficient; set => _conversionCoefficient = value ?? 0.0; } } public class UtilityElectricityConsumptionModel : UtilityConsumptionModel { // 继承父类默认的null实现即可 }
所有子类都将拥有该属性,绑定不会因找不到属性报错;非天然气类型返回null,结合TargetNullValue即可显示空内容。
内容的提问来源于stack exchange,提问作者Ludovic Wagner
相关产品推荐
相关产品推荐

