9

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}?

Community
  • 1
  • 1
snurre
  • 3,045
  • 2
  • 24
  • 31
  • 1
    I face exactly the same issue and I'm eager to see a good solution to that question ! – SvenG Dec 07 '11 at 15:26

3 Answers3

7

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>
Rachel
  • 130,264
  • 66
  • 304
  • 490
  • Do you know if the warnings in the output window have a negative performance impact? – SvenG Dec 07 '11 at 15:45
  • 2
    @SvenG I don't think so. The warnings only appear in Debug mode, and would never even exist in Release mode. Here's a related SO answer: http://stackoverflow.com/a/2594600/302677 – Rachel Dec 07 '11 at 15:53
  • 4
    The only problem is that now, depending on the size of your app, you'll end up with "warnings" in your output window, some of which might be acceptable, as you described above, and some which warrant investigation. I'd rather WPF provide a way for me to specify in the binding "don't warn me if this binding fails" and then I know that if a BindingExpression warning pops up, it's something I need to investigate. It's similar to wanting no compile-time warnings when building. If you start to allow some warnings to persist, it hinders your ability to identify real problems. – Kohanz Jun 07 '17 at 19:28
2

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.

ghord
  • 13,260
  • 6
  • 44
  • 69
0

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>
Fischermaen
  • 12,238
  • 2
  • 39
  • 56
  • This is assuming I want one or the other property displayed. If this was the case, I'd probably go for a PriorityBinding instead, but I do actually want empty values if the property is not found on the object. – snurre Dec 07 '11 at 13:11