Вот проблема. Я связываю 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, они создаются динамично из источника данных.
Править: Я нашел этот ответ, но он не работал на меня.
Используете ли вы FallbackValue для работы со связующим материалом? Это будет применяться, если переплет не удастся...
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded" Value="{Binding IsNodeExpanded, Mode=TwoWay, FallbackValue=False}" />
</Style>
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>
Попробуйте использовать свойство 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}">