I am trying to use a HierarchicalDataTemplate to recursively create expanders with items in them but when I use the HierarchicalDataTemplate I only get the first level of items displayed.

Please let me know if you need anyore information.

Heres the what the xaml would look like if I was writing by hand:

<GroupBox Header="SectionHeader">
    <StackPanel >
        <Expander VerticalAlignment="Top" Header="SubSectionHeader">
            <StackPanel>
                <Expander VerticalAlignment="Top" Header="SubSectionHeader" Margin="10,0,0,0">
                    <StackPanel>
                        etc......
                    </StackPanel>
                </Expander>
         </Expander>
    </StackPanel>
</GroupBox>

Heres what I have so far.

Xaml:

<ItemsControl Name="lstMain" ItemsSource="{Binding Sections}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <GroupBox Header="{Binding Section.SectionName}">
                <ItemsControl ItemsSource="{Binding SubSections}" ItemTemplate="{StaticResource BinderTemplate}" />
            </GroupBox>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

<HierarchicalDataTemplate x:Key="BinderTemplate" ItemsSource="{Binding Path=SubSections}" DataType="{x:Type local:SubSectionViewModel}">
    <StackPanel>
        <Expander Header="{Binding SubSection.SubSectionName}"/>
    </StackPanel>
</HierarchicalDataTemplate>

Data Classes:

class TopViewModel
{
    ObservableCollection<SectionViewModel> _sections = new ObservableCollection<SectionViewModel>();

    public ObservableCollection<SectionViewModel> Sections
    {
        get
        {
            return _sections;
        }
        set
        {
            _sections = value;
        }
    }
}

public class SectionViewModel
{
    ObservableCollection<MaterialViewModel> _materials = new ObservableCollection<MaterialViewModel>();
    ObservableCollection<SubSectionViewModel> _subSections = new ObservableCollection<SubSectionViewModel>();
    Section _section;

    public Section Section
    {
        get
        {
            return _section;
        }
        set
        {
            _section = value;
        }
    }

    public string MaterialName
    {
        get { return Section.SectionName; }
        set { Section.SectionName = value; }
    }

    public ObservableCollection<MaterialViewModel> Materials
    {
        get
        {
            return _materials;
        }
        set
        {
            _materials = value;
        }
    }

    public ObservableCollection<SubSectionViewModel> SubSections
    {
        get
        {
            return _subSections;
        }
        set
        {
            _subSections = value;
        }
    }
}

public class SubSectionViewModel
{
    ObservableCollection<MaterialViewModel> _materials = new ObservableCollection<MaterialViewModel>();
    ObservableCollection<SubSectionViewModel> _subSections = new ObservableCollection<SubSectionViewModel>();
    SubSection _subSection;

    public ObservableCollection<MaterialViewModel> Materials
    {
        get
        {
            return _materials;
        }
        set
        {
            _materials = value;
        }
    }

    public ObservableCollection<SubSectionViewModel> SubSections
    {
        get
        {
            return _subSections;
        }
        set
        {
            _subSections = value;
        }
    }

    public SubSection SubSection
    {
        get
        {
            return _subSection;
        }
        set
        {
            _subSection = value;
        }
    }
}
有帮助吗?

解决方案

You are missing a key bit in your HierarchicalDataTemplate - how to render the subelements:

<HierarchicalDataTemplate x:Key="BinderTemplate" 
    ItemsSource="{Binding Path=SubSections}" 
    DataType="{x:Type local:SubSectionViewModel}">
    <StackPanel>
        <Expander Header="{Binding SubSection.SubSectionName}">
            <ItemsControl Margin="5,0,0,0" 
                      ItemsSource="{Binding SubSections}" 
                      ItemTemplate="{DynamicResource BinderTemplate}"/>
        </Expander>
    </StackPanel>
</HierarchicalDataTemplate>

EDIT: Not to steal @BDE's thunder, but he/she's mostly correct about the use of DataType - but this is the way you'd "simplify" the above XAML:

<Window x:Class="WpfApplication1.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        xmlns:local="clr-namespace:WpfApplication1" 
        Title="Window1" Height="300" Width="300">
    <Window.Resources>
         <!-- normal template for sections -->
         <DataTemplate DataType="{x:Type local:SectionViewModel}">
            <GroupBox Header="{Binding Section.SectionName}">
                <ItemsControl ItemsSource="{Binding SubSections}"/>
            </GroupBox>
         </DataTemplate>
         <!-- hierarchical template for subsections -->
         <HierarchicalDataTemplate 
              DataType="{x:Type local:SubSectionViewModel}">
           <StackPanel>
               <Expander Header="{Binding SubSection.SubSectionName}">
                   <ItemsControl Margin="5,0,0,0" 
                         ItemsSource="{Binding SubSections}"/>
               </Expander>
           </StackPanel>
        </HierarchicalDataTemplate>
    </Window.Resources>
    <Grid>
        <!-- 
           no need to specify ItemTemplate if WPF can suss out all the item types 
         -->
        <ItemsControl Name="lstMain" ItemsSource="{Binding Sections}"/>
    </Grid>
</Window>

其他提示

An alternative to HierarchicalDataTemplate is to add an ItemsControl to the Expander in your data template, and bind the ItemsSource there.

Also, since you specify the DataType in the data template definition, so you don't have to directly set the ItemTemplate by key name for your toplevel ItemsControl.

If you modifiy you XAML like this it might do what you want:

<DataTemplate DataType="{x:Type local:SubSectionViewModel}">
    <StackPanel>
        <Expander Header="{Binding SubSection.SubSectionName}">
            <ItemsControl ItemsSource="{Binding SubSections}"/>
        </Expander>
    </StackPanel>
</DataTemplate>

<ItemsControl Name="lstMain" ItemsSource="{Binding Sections}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <GroupBox Header="{Binding Section.SectionName}">
                <ItemsControl ItemsSource="{Binding SubSections}"/>
            </GroupBox>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

Section.SectionName shall be MaterialName?

Look Lines :

    <ItemsControl ItemsSource="{Binding SubSections}" ItemTemplate="{StaticResource BinderTemplate}" />

and

    <HierarchicalDataTemplate x:Key="BinderTemplate" ItemsSource="{Binding Path=SubSections}" DataType="{x:Type local:SubSectionViewModel}">

I think, if firs line binding is SubSections, so second line instead of

   {Binding Path=SubSections} 

you probably shall write

    {Binding}

SubSectionName i do not find in your classes.

Please, add more classes

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top