Search code examples
c#wpftreeview

ItemContainerStyle for Treeview using Class with List of SubClasses


My ObservableCollection is from Type FUClass. In this Class is a List of a FUSubClass. The ListView Itemsource is bound to the ObservableCollection FUList.

My TreeView shows the GroupName and a have one TreeViewItem with the ItemName.

The Problem is that only 1 TreeViewItem with all Items from the FUSubClassList is displayed but i want to have for every Item one TreeViewItem. Dont know how to achieve that in the ItemContainerStyle.

XAML ItemContainerStyle:

<Style PresentationOptions:Freeze="True" TargetType="{x:Type ListViewItem}">
        <Setter Property="Height" Value="Auto" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ListViewItem}">
                    <TreeView Width="1248" MinHeight="50">
                        <TreeViewItem>
                            <TreeViewItem.Header>
                                <StackPanel Orientation="Horizontal">
                                    <ContentPresenter Content="{Binding GroupName}" RecognizesAccessKey="False" />
                                </StackPanel>
                            </TreeViewItem.Header>
                            <TreeViewItem ItemsSource="{Binding FUSubClassList}">
                                <TreeViewItem.Header>
                                    <Grid>
                                        <ContentPresenter Content="{Binding ItemName}" RecognizesAccessKey="False" />
                                    </Grid>
                                </TreeViewItem.Header>
                            </TreeViewItem>
                        </TreeViewItem>
                    </TreeView>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

C#

    public class FUClass : INotifyPropertyChanged
    {
        private string groupName;
        public string GroupName
        {
            get { return this.groupName; }
            set
            {
                if (this.groupName != value)
                {
                    this.groupName = value;

                    this.OnPropertyChanged(nameof(GroupName));
                }
            }
        }
        private ObservableCollection<FUSubClass> FUSubClassList = new ObservableCollection<FUSubClass>();
        public ObservableCollection<FUSubClass> FUSubClassList
        {
            get { return FUSubClassList; }
            set { FUSubClassList = value; }
        }

        public class FUSubClass : INotifyPropertyChanged
        {   
            private string itemName;
            public string ItemName
            {
                get { return this.itemName; }
                set
                {
                    if (this.itemName != value)
                    {
                        this.itemName = value;

                        this.OnPropertyChanged(nameof(ItemName));
                    }
                }
            }
            public event PropertyChangedEventHandler PropertyChanged;
            protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
            {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    private ObservableCollection<FUClass> FUList = new ObservableCollection<FUClass>();

UI

**UI**


Solution

  • Skip the ItemContainerStyle and define data templates for your data types, e.g.:

    <TreeView ItemsSource="{Binding FUList}">
        <TreeView.Resources>
            <HierarchicalDataTemplate DataType="{x:Type local:FUClass}" ItemsSource="{Binding FUSubClassList}">
                <TextBlock Text="{Binding GroupName}" />
            </HierarchicalDataTemplate>
            <DataTemplate DataType="{x:Type local:FUSubClass}">
                <TextBlock Text="{Binding ItemName}" />
            </DataTemplate>
        </TreeView.Resources>
    </TreeView>