Home > Software engineering >  Cannot add templates to TreeView resources without setting Keys
Cannot add templates to TreeView resources without setting Keys

Time:07-02

I'm trying to create a TreeView, where ItemsSource is a collection of different types of objects. Previously (VS2019) all I needed to do was to specify templates in TreeView.Resources.

<TreeView ItemsSource="{Binding collectionA}">
    <TreeView.Resources>
        <HierarchicalDataTemplate DataType="{x:Type ns:type1}" ItemsSource="{Binding collectionB}">
            <TextBlock Text="{Binding name}"/>
        </HierarchicalDataTemplate>
        <DataTemplate DataType="{x:Type ns:type2}">
            <CheckBox IsChecked="{Binding Checked}" Content="{Binding element.name}"/>
        </DataTemplate>
        <DataTemplate DataType="{x:Type ns:type3}">
            <CheckBox IsChecked="{Binding Checked}" Content="{Binding name}"/>
        </DataTemplate>
    </TreeView.Resources>
</TreeView>

Now for some reason when I try to build my project, I get an error:

All objects added to an IDictionary must have a Key attribute or some other type of key associated with them.

My understanding is that DataType should automatically generate a key ( x:Key="{x:Type ns:typeX}" ) and set a correct template. I tried defining the keys manually, but templates still don't get assigned. I managed to make it work when I added templates without keys to resources during runtime, but this is not a viable workaround.

Is this a bug in VS2022 or am I doing something wrong?

How should I make this code work? Is there a manual way of selecting templates?

CodePudding user response:

In the end I used a custom TemplateSelector to manually assign templates to objects from my collection.

public class TreeViewTemplateSelector : DataTemplateSelector
    {
        public override DataTemplate SelectTemplate(object item, DependencyObject container)
        {
            if (item is type1)
            {
                var template = new HierarchicalDataTemplate();
                Binding itemsSource = new Binding();
                itemsSource.Path = new PropertyPath("collectionB");
                template.ItemsSource = itemsSource;
                FrameworkElementFactory fef = new FrameworkElementFactory(typeof(TextBlock));
                Binding name = new Binding();
                name.Path = new PropertyPath("name");
                fef.SetBinding(TextBlock.TextProperty, name);
                template.VisualTree = fef;
                return template;
            }

            if (item is type2)
            {
                var template = new DataTemplate();
                FrameworkElementFactory fef = new FrameworkElementFactory(typeof(CheckBox));
                Binding name = new Binding();
                name.Path = new PropertyPath("element.name");
                Binding isChecked = new Binding();
                isChecked.Path = new PropertyPath("Checked");
                fef.SetBinding(CheckBox.ContentProperty, name);
                fef.SetBinding(CheckBox.IsCheckedProperty, isChecked);
                template.VisualTree = fef;
                return template;
            }

            if (item is type3)
            {
                var template = new DataTemplate();
                FrameworkElementFactory fef = new FrameworkElementFactory(typeof(CheckBox));
                Binding name = new Binding();
                name.Path = new PropertyPath("name");
                Binding isChecked = new Binding();
                isChecked.Path = new PropertyPath("Checked");
                fef.SetBinding(CheckBox.ContentProperty, name);
                fef.SetBinding(CheckBox.IsCheckedProperty, isChecked);
                template.VisualTree = fef;
                return template;
            }

            return null;
        }
    }

And in xaml:

<UserControl.Resources>
        <ns:TreeViewTemplateSelector x:Key="templateSelector"/>
</UserControl.Resources>

(...)

<TreeView ItemsSource="{Binding collectionA}" ItemTemplateSelector="{StaticResource templateSelector}">

  • Related