当源对象可能没有给定属性时如何处理绑定?

时间:2011-12-07 12:03:51

标签: c# wpf binding fallbackvalue

我有两个具有不同属性的类,但都继承了其他一些基类:

public class BaseClass { }

public class ClassA : BaseClass
{
    public string PropertyA { get; set; }
}

public class ClassB : BaseClass
{
    public string PropertyB { get; set; }
}

代码隐藏:

public ObservableCollection<BaseClass> Items { get; set; }

public MainWindow()
{
    Items = new ObservableCollection<BaseClass>
        {
            new ClassA {PropertyA = "A"},
            new ClassB {PropertyB = "B"}
        };
}

我的XAML看起来像这样:

<ListView ItemsSource="{Binding Items}">
    <ListView.View>
        <GridView>
            <GridViewColumn DisplayMemberBinding="{Binding PropertyA, FallbackValue=''}"/>
            <GridViewColumn DisplayMemberBinding="{Binding PropertyB, FallbackValue={x:Null}}"/>
        </GridView>
    </ListView.View>
</ListView>

在调试模式下运行时,输出窗口显示:

  

System.Windows.Data警告:40:BindingExpression路径错误:&#39; PropertyB&#39;在&#39; object&#39;上找不到的属性&#39;&#39; ClassA的&#39; (的HashCode = 66437409)&#39 ;. BindingExpression:路径= PropertyB;的DataItem =&#39; ClassA的&#39; (的HashCode = 66437409);目标元素是&#39; TextBlock&#39; (名称=&#39;&#39);目标属性是&#39; Text&#39; (键入&#39; String&#39;)

     

System.Windows.Data警告:40:BindingExpression路径错误:&#39; PropertyA&#39;在&#39; object&#39;上找不到的属性&#39;&#39; ClassB的&#39; (的HashCode = 2764078)&#39 ;. BindingExpression:路径= PropertyA;的DataItem =&#39; ClassB的&#39; (的HashCode = 2764078);目标元素是&#39; TextBlock&#39; (名称=&#39;&#39);目标属性是&#39; Text&#39; (键入&#39; String&#39;)

有没有更好的方法来处理像这样的绑定?是否有任何性能影响,使用FallbackValue =&#39;&#39;是否更好?或FallbackValue = {x:Null}?

3 个答案:

答案 0 :(得分:6)

就个人而言,我只是忽略它们。如果某个项目不存在,它将显示为空字符串,这通常是我喜欢的。

它们是调试窗口中的警告,因为它们只是警告,而不是错误。他们会警告你一个可能存在的问题,但是如果忽略它们就不会发生任何不好的事情。

如果它真的困扰你,你可以使用模板列并为不同的对象类型指定不同的DataTemplates。

<DataTemplate TargetType="{x:Type local:ClassA}">
    <TextBlock Text="{Binding PropertyA}" />
</DataTemplate>

<DataTemplate TargetType="{x:Type local:ClassB}">
    <TextBlock Text="{Binding PropertyB}" />
</DataTemplate>

我有时也会使用返回typeof(value)的转换器,并在DataTrigger中使用该类型

<Style.Triggers>
    <DataTrigger Value="{x:Type local:ClassA}" 
                 Binding="{Binding Converter={StaticResource ObjectToTypeConverter}}">
        <Setter Property="Text" Value="{Binding PropertyA}" />
    </DataTrigger>
    <DataTrigger Value="{x:Type local:ClassB}" 
                 Binding="{Binding Converter={StaticResource ObjectToTypeConverter}}">
        <Setter Property="Text" Value="{Binding PropertyB}" />
    </DataTrigger>
</Style.Triggers>

答案 1 :(得分:1)

消除此警告的简便方法是使用{snurre提到的PriorityBinding,如下所示:

<GridViewColumn.DisplayMemberBinding>
    <PriorityBinding>
        <Binding Path="PropB" />
    </PriorityBinding>
</GridViewColumn.DisplayMemberBinding>

对于缺少PropB属性的警告不会出现。

答案 2 :(得分:0)

我更喜欢以下方式:

编写实现IMultiValueConverter的自定义值转换器。在此转换器中,您可以检查传入值,选择有效值并返回该值。

在Xaml中添加一个类似的MultiBinding:

<MultiBinding Converter="{StaticResource ResourceKey=myMultiValueConverter}" ConverterParameter="SomeParameterIfNecessary">
    <Binding "ToTheFirstClass.PropertyA" />
    <Binding "ToTheSecondClass.PropertyB" />
</MultiBinding>