How can I add additional item templates to an extended WPF treeview
I'm trying to set up a Treeview descendent class that can be used as a common template for all Treeview instances in my application, but with additional formatting and templates for each instance.
For the base, I have a UserControl that descends from Treeview, with the common styles and a single standard data template
<TreeView x:Class="BaseTreeView" ... >
<TreeView.ItemContainerStyle> ... </TreeView.ItemContainerStyle>
<TreeView.Resources>
<HierarchicalDataTemplate ItemsSource="{Binding Children}" DataType="{x:Type local:BaseTreeViewItem}">
<TextBlock Text="{Binding Caption}" />
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
Then in each window, I use this extended Treeview and add additional data templates for the specific TreeviewItems I'm displaying.
e.g.
<Window x:Class="Window1" ... >
...
<BaseTreeView ItemsSource="{Binding RootTreeItems}" >
<MyTreeView.Resources>
<HierarchicalDataTemplate ItemsSource="{Binding Children}" DataType="{x:Type ExtendedTreeViewItem1}">
<StackPanel Orientation="Horizo开发者_如何学JAVAntal">
<Image Source="Images/Image1.png" />
<TextBlock Text="{Binding Caption}" />
</StackPanel>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type ExtendedTreeViewItem2}">
<StackPanel Orientation="Horizontal">
<Image Source="Images/Image2.png" />
<TextBlock Text="{Binding Caption}" />
</StackPanel>
</DataTemplate>
</MyTreeView.Resources>
</BaseTreeView>
...
</Window>
This compiles fine, but at runtime I get an error
"'Set property 'System.Windows.ResourceDictionary.DeferrableContent' threw an exception.' Line number '27' and line position '59'."
"Cannot re-initialize ResourceDictionary instance."
Is there any way around this, or can someone suggest a better way to set up a base treeview template and multiple descedent versions.
You could try moving your templates to the <Window.Resources>
instead of <MyTreeView.Resources>
If it doesn't work, maybe using a DataTemplateSelector suits your case best. You can create a DataTemplateSelector class like this:
public class ExtendedTreeViewTemplateSelector : DataTemplateSelector
{
public DataTemplate ExtendedTreeViewItem1Template { get; set; }
public DataTemplate ExtendedTreeViewItem2Template { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (item is ExtendedTreeViewItem1)
return ExtendedTreeViewItem1Template;
if (item is ExtendedTreeViewItem2)
return ExtendedTreeViewItem2Template;
}
}
And then use it in your XAML like this:
<Window x:Class="Window1" ... >
<Window.Resources>
<HierarchicalDataTemplate x:Key="extendedTreeViewItem1Template" ItemsSource="{Binding Children}" DataType="{x:Type ExtendedTreeViewItem1}">
<StackPanel Orientation="Horizontal">
<Image Source="Images/Image1.png" />
<TextBlock Text="{Binding Caption}" />
</StackPanel>
</HierarchicalDataTemplate>
<DataTemplate x:Key="extendedTreeViewItem2Template" DataType="{x:Type ExtendedTreeViewItem2}">
<StackPanel Orientation="Horizontal">
<Image Source="Images/Image2.png" />
<TextBlock Text="{Binding Caption}" />
</StackPanel>
</DataTemplate>
<selector:ExtendedTreeViewTemplateSelector x:Key="treeViewTemplateSelector"
ExtendedTreeViewItem1Template="{StaticResource extendedTreeViewItem1Template}"
ExtendedTreeViewItem2Template="{StaticResource extendedTreeViewItem2Template}" />
</Window.Resources>
...
<BaseTreeView ItemsSource="{Binding RootTreeItems}"
ItemTemplateSelector={StaticResource treeViewTemplateSelector}" />
...
</Window>
精彩评论