Search code examples
c#wpfxamltreeviewitemtemplate

Load ItemTemplate when add items manually to a TreeView?


I'm creating my nodes (TreeViewItems) manually, I mean in code behind. I'm doing this because I'm loding subitems on demand when is expand and I have to add a dummy node. That's the reason why I'm adding items manualy.

Now, the big deal is when I create a TreeViewItem does not display the DataTemplate and show the default. The output window does not tell anything.

        DataTemplate dt1 = this.Resources["exerciseSetTemplate"] as DataTemplate;

        foreach (var qs in qss)
        {
            TreeViewItem tvi = new TreeViewItem();
            tvi.Header = qs.SetName;
            tvi.Tag = qs;
            tvi.ItemTemplate = dt1;
            tvi.Items.Add(yourDummyNode);

            treeView1.Items.Add(tvi);
        }

Here is my XAML Code:

<UserControl.Resources>
    <DataTemplate x:Key="questionSetTemplate">
        <StackPanel Orientation="Horizontal" Height="20" Margin="2,0,2,0">
            <Image Width="16" Height="16" Source="{StaticResource FolderImage}" Margin="0,0,5,0" />
            <TextBlock Text="{Binding SetName}" />
        </StackPanel>
    </DataTemplate>
</UserControl.Resources>

<Grid>
    <TreeView x:Name="treeView1" TreeViewItem.Expanded="treeView1_Expanded_1"
              ScrollViewer.HorizontalScrollBarVisibility="Disabled">
    </TreeView>
</Grid>

What can I do to display the DataTemplate?


Solution

  • I think the best option is to not add the objects directly to the TreeView Items property (as this will ignore DataTemplates) and create a Collection to add these items to and bind that to your TreeView, Then you can remove the x:Key property of your DataTemplate and use the DataType, this will apply the template to any objects of that type in the collection to your TreeView.

    Example:

    <UserControl x:Class="WpfApplication8.UserControl1"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 xmlns:local="clr-namespace:WpfApplication8"
                 mc:Ignorable="d" 
                 d:DesignHeight="300" d:DesignWidth="300" Name="UI">
        <UserControl.Resources>
            <DataTemplate DataType="{x:Type local:MyObject}">
                <StackPanel Orientation="Horizontal" Height="20" Margin="2,0,2,0">
                    <!--<Image Width="16" Height="16" Source="{StaticResource FolderImage}" Margin="0,0,5,0" />-->
                    <TextBlock Text="{Binding SetName}" Foreground="Red"/>
                </StackPanel>
            </DataTemplate>
        </UserControl.Resources>
    
        <Grid DataContext="{Binding ElementName=UI}">
            <TreeView x:Name="treeView1" ItemsSource="{Binding TreeItems}" ScrollViewer.HorizontalScrollBarVisibility="Disabled" />
        </Grid>
    </UserControl>
    

    Code:

    public partial class UserControl1 : UserControl
    {
        public UserControl1()
        {
            InitializeComponent();
    
            //  foreach (var qs in qss)
            for (int i = 0; i < 50; i++)
            {
                // TreeItems.Add(qs);
                TreeItems.Add(new MyObject { SetName = "Test1" }); 
            }
        } 
    
        private ObservableCollection<MyObject> _treeItems = new ObservableCollection<MyObject>();
        public ObservableCollection<MyObject> TreeItems
        {
            get { return _treeItems; }
            set { _treeItems = value; }
        }
    }
    
    
    // Your "qs" object
    public class MyObject : INotifyPropertyChanged
    {
        private string _folderImage;
        public string FolderImage
        {
            get { return _folderImage; }
            set { _folderImage = value; NotifyPropertyChanged("FolderImage"); }
        }
    
        private string _setname;
        public string SetName
        {
            get { return _setname; }
            set { _setname = value; NotifyPropertyChanged("SetName"); }
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(string property)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(property));
            }
        }
    }