Question

I have two classes with different properties, but both inherit some other base class:

public class BaseClass { }

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

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

Code-behind:

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

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

And my XAML looks like this:

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

When running in debug mode, the output window shows this:

System.Windows.Data Warning: 40 : BindingExpression path error: 'PropertyB' property not found on 'object' ''ClassA' (HashCode=66437409)'. BindingExpression:Path=PropertyB; DataItem='ClassA' (HashCode=66437409); target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')

System.Windows.Data Warning: 40 : BindingExpression path error: 'PropertyA' property not found on 'object' ''ClassB' (HashCode=2764078)'. BindingExpression:Path=PropertyA; DataItem='ClassB' (HashCode=2764078); target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')

Is there a better way of handling bindings like these? Are there any performance implications, and is it better to use FallbackValue='' or FallbackValue={x:Null}?

Was it helpful?

Solution

Personally I just ignore them. If an item doesn't exist, it gets displayed as an empty string, which is usually what I prefer.

They are warnings in the debug window because they are simply warnings, not errors. They're warning you of a possible problem, but nothing bad will happen if you ignore them.

If it really bothers you, you can probably use a Template Column and specify different DataTemplates for the different object types.

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

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

I will also sometimes use a Converter which returns typeof(value), and use that type in a 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>

OTHER TIPS

Easy option to eliminate this warning is to use PriorityBinding as mentioned by @snurre like this:

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

Warning will not appear for missing PropB property.

I would prefer following way:

Write a custom value converter implementing IMultiValueConverter. In this converter you can check the incoming values, choose the valid one and give that value back.

In Xaml add a MultiBinding like that:

<MultiBinding Converter="{StaticResource ResourceKey=myMultiValueConverter}" ConverterParameter="SomeParameterIfNecessary">
    <Binding "ToTheFirstClass.PropertyA" />
    <Binding "ToTheSecondClass.PropertyB" />
</MultiBinding>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top