如何为 WPF TreeView 设置 DataTemplate 以显示列表的所有元素?

Posted

技术标签:

【中文标题】如何为 WPF TreeView 设置 DataTemplate 以显示列表的所有元素?【英文标题】:How do I set a DataTemplate for a WPF TreeView to display all Elements of an List? 【发布时间】:2013-07-18 11:50:25 【问题描述】:

我想在 WPF 中使用 TreeViews 可视化以下数据结构:

class MyDataContext

    ICollectionView Outers get;set;
    //...


class Outer

    string Name get;set;
    IEnumberable<Inner> Actions get;set; 



class Inner

    string Description get;set;
    Command OnClick get;set;

这是我目前的尝试:

<!-- DataContext is MyDataContext at this  point -->
<TreeView ItemsSource="Binding Path=Outers">
    <TreeView.Resources>
        <DataTemplate DataType="x:Type myns:Outer">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="Binding Path=Name"/>

                <TreeView ItemsSource="Binding Path=Actions" >
                    <DataTemplate DataType="x:Type myns:Inner">
                        <Button Command=Binding Path=OnClick>
                            <TextBlock Text="Binding Path=Description"/>
                        </Button>
                    </DataTemplate>
                </TreeView>
            </StackPanel>
        </DataTemplate>
    </TreeView.Resources>
</TreeView>

由于我收到以下InvalidOperationException

Operation is not valid while ItemsSource is in use. Access and modify elements with ItemsControl.ItemsSource instead.

如果我放弃内部 TreeView 也不例外(当然也没有按钮)。

【问题讨论】:

【参考方案1】:

我使用了 Mateusz 提到的页面 (HierarchicalDataTemplate),在阅读了这个问题的答案后:Bind Collection to StackPanel 我找到了一个符合我要求的解决方案:

这里的球员(3 级)与球队(2 级)在同一排:

<TreeView ItemsSource="Binding League">
    <!-- Conference template -->
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="Binding Teams">
            <TextBlock Foreground="Red" Text="Binding Name" />
            <!-- Team template -->
            <HierarchicalDataTemplate.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="Binding Name"/>
                        <ItemsControl ItemsSource="Binding Players">
                            <ItemsControl.ItemsPanel>
                                <ItemsPanelTemplate>
                                    <StackPanel Orientation="Horizontal">
                                    </StackPanel>
                                </ItemsPanelTemplate>
                            </ItemsControl.ItemsPanel>
                            <ItemsControl.ItemTemplate>
                                <DataTemplate>
                                    <Button Content="Binding "/>
                                </DataTemplate>
                            </ItemsControl.ItemTemplate>
                        </ItemsControl>
                    </StackPanel>
                </DataTemplate>
            </HierarchicalDataTemplate.ItemTemplate>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

【讨论】:

【参考方案2】:

请尝试将 HierarchicalDataTemplate 与 TreeView 一起使用。

HierarchicalDataTemplate

【讨论】:

我查看了您提到的网站,但仍然不知道如何将操作作为与“外部”元素位于同一行的按钮。此页面上的示例会将每个按钮放在“Outer”元素下方的新行中。【参考方案3】:

也许这对你有一点帮助;)

xaml:

    <TreeView ItemsSource="Binding Outers">
        <TreeView.ItemTemplate>
            <DataTemplate>
                <TreeViewItem ItemsSource="Binding Actions" Header="Binding Name">
                    <TreeViewItem.ItemTemplate>
                        <DataTemplate>
                            <Button Command="Binding Click" Content="Binding Name" />
                        </DataTemplate>
                    </TreeViewItem.ItemTemplate>
                </TreeViewItem>
            </DataTemplate>
        </TreeView.ItemTemplate>
    </TreeView>

数据:

public partial class MainWindow : Window

    public MainWindow()
    
        InitializeComponent();

        DataContext = new MyDataContext();
    




    class MyDataContext
    
        public ObservableCollection<Outer> Outers  get; set; 


        public MyDataContext()
        
            Outers = new ObservableCollection<Outer>();
            Outers.Add(new Outer()  Name = "Herp" );
            Outers.Add(new Outer()  Name = "Derp" );
        
    

    class Outer
    
        public string Name  get; set; 
        public ObservableCollection<Inner> Actions  get; set; 

        public Outer()
        
            Actions = new ObservableCollection<Inner>();
            Actions.Add(new Inner  Name = "Test1" );
            Actions.Add(new Inner  Name = "Test2" );
            Actions.Add(new Inner  Name = "Test3" );
            Actions.Add(new Inner  Name = "Test4" );
            Actions.Add(new Inner  Name = "Test5" );
            Actions.Add(new Inner  Name = "Test6" );
            Actions.Add(new Inner  Name = "Test7" );
        
    


    class Inner
    
        public string Name  get; set; 
        public ICommand OnClick  get; set; 
    

如果您使用的是命令... 试试这个例子: ICommand

【讨论】:

以上是关于如何为 WPF TreeView 设置 DataTemplate 以显示列表的所有元素?的主要内容,如果未能解决你的问题,请参考以下文章

如何为 WPF 故事板中的静态对象设置动画

我在wpf中使用了自定义的控件,请问如何为自定义控件中的一个按钮设置快捷键?

如何为 ListView 控件中的第一个 WPF RadioButton 设置 XAML,以便默认检查?

如何处理在WPF TreeView中显示数据的大延迟

WPF TreeView 虚拟化-设置滚动到选中项

WPF Grid - 如何为一列应用样式?