Как обрабатывать привязки, когда исходный объект может не иметь заданного свойства? - PullRequest
7 голосов
/ 07 декабря 2011

У меня есть два класса с разными свойствами, но оба наследуют другой базовый класс:

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: свойство 'PropertyB' не найдено для 'объекта' '' ClassA '(HashCode = 66437409)'. BindingExpression: Path = PropertyB; DataItem = 'ClassA' (HashCode = 66437409); целевым элементом является TextBlock (Name = ''); Целевым свойством является «Текст» (тип «Строка»)

System.Windows.Data Предупреждение: 40: ошибка пути BindingExpression: свойство 'PropertyA' не найдено в 'объекте' '' ClassB '(HashCode = 2764078)'. BindingExpression: Path = PropertyA; DataItem = 'ClassB' (HashCode = 2764078); целевым элементом является TextBlock (Name = ''); Целевым свойством является «Текст» (тип «Строка»)

Есть ли лучший способ обработки таких привязок? Есть ли какие-либо последствия для производительности, и лучше ли использовать FallbackValue = '' или FallbackValue = {x: Null}?

Ответы [ 3 ]

6 голосов
/ 07 декабря 2011

Лично я их просто игнорирую. Если элемент не существует, он отображается в виде пустой строки, как правило, то, что я предпочитаю.

Это предупреждения в окне отладки, потому что это просто предупреждения, а не ошибки. Они предупреждают вас о возможной проблеме, но ничего плохого не случится, если вы их проигнорируете.

Если это действительно вас беспокоит, вы, вероятно, можете использовать столбец шаблона и указать разные шаблоны данных для разных типов объектов.

<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 голос
/ 27 сентября 2018

Простой способ устранить это предупреждение - использовать PriorityBinding, как упомянуто @snurre:

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

Предупреждение не появится для отсутствующего PropB свойства.

0 голосов
/ 07 декабря 2011

Я бы предпочел следующий способ:

Написать пользовательский преобразователь значений, реализующий IMultiValueConverter.В этом конвертере вы можете проверить входящие значения, выбрать действительные и вернуть это значение.

В Xaml добавьте MultiBinding так:

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