Randy Gamage
Randy Gamage

Reputation: 1941

Using TreeView in WPF

I'm trying to display a simple tree structure in WPF, and it's working but it shows all levels of nodes, at the top level of the tree. I have 9 nodes total in the structure, but only one should show at the root level. Under that should be two nodes, under those a couple, etc. Under each node, it does show the proper sub-nodes, but in addition it shows all nodes at the top. Here are my objects (these are EF db objects, if it matters):

    public class ProductGroup
{
    public int ProductGroupId { get; set; }
    public ProductGroup Parent { get; set; }
    public string Description { get; set; }

    private ProductGroup() //not used, but needed to prevent EF error
    {
        Description = string.Empty;
    }
    public ProductGroup(string description)
    {
        Description = description;
    }
    public virtual ICollection<ProductGroup> Children { get; set; }

    public void Add(ProductGroup newItem)
    {
        newItem.Parent = this;
        if (Children == null)
            Children = new Collection<ProductGroup>();
        Children.Add(newItem);
    }
    public int Count
    {
        get { return Children.Count; }
    }
}

And here is the xaml:

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:ConfiguratorDB="clr-namespace:ConfiguratorDB;assembly=ConfiguratorDB" mc:Ignorable="d" x:Class="ConfiguratorDBTest.Window2"
    xmlns:local="clr-namespace:ConfiguratorDB;assembly=ConfiguratorDB"
Title="Window2" Height="417" Width="712" Loaded="Window_Loaded_1">
<Window.Resources>
    <CollectionViewSource x:Key="productGroupViewSource" d:DesignSource="{d:DesignInstance {x:Type ConfiguratorDB:ProductGroup}, CreateList=True}"/>
</Window.Resources>
<Grid DataContext="{StaticResource productGroupViewSource}">
    <DataGrid x:Name="productGroupDataGrid" AutoGenerateColumns="False" EnableRowVirtualization="True" ItemsSource="{Binding}" Margin="23,36,346,151" RowDetailsVisibilityMode="VisibleWhenSelected">
        <DataGrid.Columns>
            <DataGridTextColumn x:Name="descriptionColumn" Binding="{Binding Description}" Header="Description" Width="SizeToHeader"/>
            <DataGridTextColumn x:Name="productGroupIdColumn" Binding="{Binding ProductGroupId}" Header="Product Group Id" Width="SizeToHeader"/>
        </DataGrid.Columns>
    </DataGrid>
    <TreeView x:Name="productGroupTreeView" ItemsSource="{Binding}" Margin="396,38,73,111">
        <TreeView.Resources>
            <HierarchicalDataTemplate DataType="{x:Type local:ProductGroup}" ItemsSource="{Binding Children}">
                <TextBlock Text="{Binding Path=Description}" />
            </HierarchicalDataTemplate>
        </TreeView.Resources>
    </TreeView>
</Grid>

Here's what the output looks like. There shouldn't be any duplicates shown: Picture of Output

Upvotes: 0

Views: 809

Answers (1)

Randy Gamage
Randy Gamage

Reputation: 1941

I was able to get the treeview to display correctly by filtering the CollectionViewSource based on whether the node was the root node. Basically you only want the root to be returned. The children will be handled by the hierarchical data template. Here are the lines of code I added to the codebehind of the window:

productGroupViewSource.Filter += productGroupViewSource_Filter;

void productGroupViewSource_Filter(object sender, FilterEventArgs e)
{
    var node = (ProductGroup) e.Item;
    e.Accepted = node.Parent == null;
}

Upvotes: 0

Related Questions