Reputation: 47
I have my own treeview implementation based on this post, but I have problems defining a different style based on what object type is in the treeviewitem. I know the simple way is to define a templateselector, but I can't figure out how this would work when you have two HierarchicalDataTemplates.
<HierarchicalDataTemplate DataType="{x:Type domainLayer:Folder}" ItemsSource="{Binding Converter={StaticResource BaseTypeConverter}}" />
<HierarchicalDataTemplate DataType="{x:Type domainLayer:Document}" ItemsSource="{Binding Converter={StaticResource BaseTypeConverter}}" />
I use these templates to lazy load my tree, which works fine. There's also a Style defined for all TreeListViewItems. Maybe there's a solution too, but I can't figure out how to define if my TreeListViewItem is either a Folder or a Document.
Any help is much appreciated. If you need more code, just let me know!
Update 10:40am:
In a Style the row is defined for every TreeListViewItem:
<Style x:Key="cxc" TargetType="{x:Type local:TreeListViewItem}">
<Setter Property="FontFamily" Value="TradeGothic LT" />
<Setter Property="FontSize" Value="14px" />
<Setter Property="Foreground" Value="{StaticResource TextBrush}" />
<Setter Property="Background" Value="Transparent" />
<EventSetter Event="MouseDoubleClick" Handler="OnItemMouseDoubleClick" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:TreeListViewItem}">
<StackPanel>
<Border Name="Bd"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}">
<GridViewRowPresenter x:Name="PART_Header"
Content="{TemplateBinding Header}"
Columns="{Binding Path=Columns,RelativeSource={RelativeSource AncestorType={x:Type local:TreeListView}}}"
/>
</Border>
<ItemsPresenter x:Name="ItemsHost" />
</StackPanel>
<ControlTemplate.Triggers>
<!-- ... -->
When I copy the template (everything in the StackPanel tag) to the HierarchicalDataTemplate I get an error: Cannot find the static member 'BackgroundProperty' on the type 'ContentPresenter'.
Upvotes: 0
Views: 3133
Reputation: 69979
You seem to be a little bit confused by the different Template
s that WPF provides. First, we can define a Style
for the TreeViewItem
(the ItemContainerStyle
), the data item 'container'. Then we can define a DataTemplate
for the data item that appears within the container (the ItemTemplate
), or HierarchicalDataTemplate
in your case.
So don't try to put your data item Binding
in the ItemContainerStyle
and don't put your UI element Binding
in the DataTemplate
and you should be fine. Note that you can supply one DataTemplate
/HierarchicalDataTemplate
without setting their x:Key
property for each data type in your collection and there is no need to use a DataTemplateSelector
... let WPF do the implicit selecting of DataTemplate
s based on the data item's types. Here is a simple example:
In code:
public class BaseClass { }
public class ClassA : BaseClass { }
public class ClassB : BaseClass { }
...
public Observablecollection<BaseClass> Items { get ; set; }
In XAML:
<ListBox ItemsSource="{Binding Items}">
<ListBox.Resources>
<DataTemplate DataType="{x:Type DataTypes:ClassA}">
<Ellipse Fill="Red" />
</DataTemplate>
<DataTemplate DataType="{x:Type DataTypes:ClassB}">
<Rectangle Fill="Blue" />
</DataTemplate>
</ListBox.Resources>
</ListBox>
This ListBox
would display red circles for the ClassA
items and blue rectangles for the ClassB
items. You can do a similar thing for your folders and files
Upvotes: 1
Reputation: 47
I've solved my problem as follows. In the aforementioned Style I've added a new MultiDataTrigger:
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition
Binding="{Binding RelativeSource={RelativeSource Self}, Path=Header, Converter={StaticResource IsFolder}}"
Value="False" />
<Condition
Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsSelected}"
Value="True" />
</MultiDataTrigger.Conditions>
<Setter TargetName="Bd"
Property="Background"
Value="{StaticResource HighlightBackgroundBrush}" />
</MultiDataTrigger>
This seems to work and looks like the proper solution. Thanks, Sheridan for the background on this.
Upvotes: 0