WPF, Устанавливающий стиль на основе типа данных?

Вот проблема. Я связываю TreeView с несколькими различными типами объектов. Каждый объект является узлом, и НЕКОТОРЫЕ объекты имеют свойство под названием IsNodeExpanded, и конечно, некоторые другие не делают. Вот мой стиль:


Теперь, проблема при привязке объектов, которые не имеют этого свойства, мы получаем эту ошибку в выводе:

System.Windows.Data Error: 39 : BindingExpression path error: 'IsNodeExpanded' property not found on 'object' ''CompensationChannel' (HashCode=56992474)'. BindingExpression:Path=IsNodeExpanded; DataItem='CompensationChannel' (HashCode=56992474); target element is 'TreeViewItem' (Name=''); target property is 'IsExpanded' (type 'Boolean')

Конечно, мы получаем его тонна времен. Таким образом, я пытаюсь придумать способ переключить стиль TreeViewItem на основе DataType, он содержит. Какая-либо идея о том, как сделать это?

Некоторая информация: Я не могу сделать этого вручную для каждого объекта, потому что я не создаю их в XAML, они создаются динамично из источника данных.

Править: Я нашел этот ответ, но он не работал на меня.

5
задан Community 23 May 2017 в 10:28
поделиться

3 ответа

Используете ли вы FallbackValue для работы со связующим материалом? Это будет применяться, если переплет не удастся...

<Style TargetType="{x:Type TreeViewItem}">
    <Setter Property="IsExpanded" Value="{Binding IsNodeExpanded, Mode=TwoWay, FallbackValue=False}" />
</Style>
0
ответ дан 14 December 2019 в 04:39
поделиться

UPDATE

<TreeView.Resources>

    ... following is only for one type of data
    <HierarchicalDataTemplate 
      DataType="{x:Type local:RegionViewModel}" 
      ItemsSource="{Binding Children}"
      >

      ... define your style
      <HierarchicalDataTemplate.ItemContainerStyle>
           <Style TargetType="{x:Type TreeViewItem}" 
                  ... following line is necessary
                  BasedOn="{StaticResource {x:Type TreeViewItem}}">
                ..... your binding stuff....
           </Style>
      </HierarchicalDataTemplate.ItemContainerStyle>

      <StackPanel Orientation="Horizontal">
        <Image Width="16" Height="16" 
           Margin="3,0" Source="Images\Region.png" />
        <TextBlock Text="{Binding RegionName}" />
      </StackPanel>
    </HierarchicalDataTemplate>
...
</TreeView.Resources>

ALTERNATIVE WAY

Вместо переключения стилей следует использовать HierarchicalDataTemplate и DataTemplate для создания стиля TreeViewItem, они будут работать аналогично, если только вы не захотите изменить определенные унаследованные свойства фреймворка.

Вы можете определить различные "DataTemplate" и "HeirarchicalDataTemplate", основываясь на различных типах объектов, которые привязаны к элементам шаблона TreeView.

И именно поэтому эти шаблоны предназначены для того, чтобы полностью отделить вашу логику и код пользовательского интерфейса, используя Selector и т.д. или любую другую подобную кодировку, вы будете вводить зависимость пользовательского интерфейса больше от вашего кода, за которым стоит WPF, который не предназначен.

Вот ссылка, TreeView DataBinding

И посмотрите, как можно определить шаблоны элементов в ресурсах,

<TreeView.Resources>
    <HierarchicalDataTemplate 
      DataType="{x:Type local:RegionViewModel}" 
      ItemsSource="{Binding Children}"
      >
      <StackPanel Orientation="Horizontal">
        <Image Width="16" Height="16" 
           Margin="3,0" Source="Images\Region.png" />
        <TextBlock Text="{Binding RegionName}" />
      </StackPanel>
    </HierarchicalDataTemplate>

    <HierarchicalDataTemplate 
      DataType="{x:Type local:StateViewModel}" 
      ItemsSource="{Binding Children}"
      >
      <StackPanel Orientation="Horizontal">
        <Image Width="16" Height="16" 
          Margin="3,0" Source="Images\State.png" />
        <TextBlock Text="{Binding StateName}" />
      </StackPanel>
    </HierarchicalDataTemplate>

    <DataTemplate DataType="{x:Type local:CityViewModel}">
      <StackPanel Orientation="Horizontal">
        <Image Width="16" Height="16" 
           Margin="3,0" Source="Images\City.png" />
        <TextBlock Text="{Binding CityName}" />
      </StackPanel>
    </DataTemplate>
  </TreeView.Resources>
1
ответ дан 14 December 2019 в 04:39
поделиться

Попробуйте использовать свойство TreeView.itemcontainerStyLeselector с помощью таможенного класса styleselector , который меняет стиль в зависимости от того, что связанный объект имеет это свойство или нет.

public class TreeItemStyleSelector : StyleSelector
{
    public Style HasExpandedItemStyle { get; set; }
    public Style NoExpandedItemStyle { get; set; }

    public override Style SelectStyle(object item, DependencyObject container)
    {
        // Choose your test
        bool hasExpandedProperty = item.GetType().GetProperty("IsExpanded") != null;

        return hasExpandedProperty
                   ? HasExpandedItemStyle
                   : NoExpandedItemStyle;
    }
}

В ресурсах XAML:

<Style x:Key="IsExpandedStyle" TargetType="{x:Type TreeViewItem}">
    <Setter Property="IsExpanded" Value="{Binding IsNodeExpanded, Mode=TwoWay}" />
</Style>

<Style x:Key="NoExpandedStyle" TargetType="{x:Type TreeViewItem}">
</Style>

<x:TreeViewItemStyleSelector x:Key="TreeViewItemStyleSelector"
                             HasExpandedItemStyle="{StaticResource IsExpandedStyle}"
                             NoExpandedItemStyle="{StaticResource NoExpandedStyle}" />

в XAML:

<TreeView ItemsSource="{Binding ...}"
          ItemContainerStyleSelector="{StaticResource TreeItemStyleSelector}">
7
ответ дан 14 December 2019 в 04:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: