TreeView,分层数据模板和递归数据。

19

对于我的树形视图,我有两个不同的类提供ItemsSource。

public class TreeViewModel : ViewModelBase
{
    public ObservableCollection<NodeViewModel> Items { get; set; }
}

public class NodeViewModel : ViewModelBase
{
    public string Id { get; set; }
    public string Name { get; set; }
    public ObservableCollection<NodeViewModel> Children { get; set; }
}

现在我想让我的TreeView显示TreeViewModel中提供的项目,并按照NodeViewModel提供的层次结构数据显示。
这是我的XAML:
<Window x:Class="TreeViewMasterDetails.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:TreeViewMasterDetails" 
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <TreeView Height="Auto" 
                  HorizontalAlignment="Stretch" 
                  Margin="10" 
                  VerticalAlignment="Stretch" 
                  Width="Auto">
            <TreeView.Resources>
                <HierarchicalDataTemplate DataType="x:Type local:TreeViewModel" ItemsSource="{Binding Items}">
                    <TextBlock Text="{Binding Path=Name}"></TextBlock>
                </HierarchicalDataTemplate>
                <HierarchicalDataTemplate DataType="x:Type local:NodeViewModel" ItemsSource="{Binding Children}">
                    <TextBlock Text="{Binding Name}"></TextBlock>
                </HierarchicalDataTemplate>
            </TreeView.Resources>
        </TreeView>
    </Grid>
</Window>

我已经尝试将Items作为TreeViewItemsSource,但是如果显示任何内容,则不会以分层方式显示数据。

我还尝试使用ItemTemplate代替TreeView.Resources

这有什么问题吗?

也许第一个TextBlock Text Binding存在问题?我想在那里显示NodeViewModelItemsName属性。


是的,我已经看到了。但是在这里不起作用。 - Mare Infinitus
TreeViewModel没有Name属性,但这可能不是问题的原因。 - Oliver
在Windows Phone上做这个有什么好运气吗? - Mathias Lykkegaard Lorenzen
2个回答

34
你只需要声明 NodeViewModelHierarchicalDataTemplate,因为这是在 TreeView 中显示的唯一内容,然后将实际的 ItemSource 绑定到 TreeView
<TreeView ItemsSource="{Binding Items}">
    <TreeView.Resources>
        <HierarchicalDataTemplate DataType="{x:Type local:NodeViewModel}" ItemsSource="{Binding Children}">
            <TextBlock Text="{Binding Name}"></TextBlock>
        </HierarchicalDataTemplate>
    </TreeView.Resources>
</TreeView>

完整示例

Xaml:

<Window x:Class="WpfApplication13.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication13"
        Title="MainWindow" x:Name="UI" Width="343" Height="744.625" >

    <TreeView DataContext="{Binding ElementName=UI, Path=TreeModel}" ItemsSource="{Binding Items}">
        <TreeView.Resources>
            <HierarchicalDataTemplate DataType="{x:Type local:NodeViewModel}" ItemsSource="{Binding Children}">
                <TextBlock Text="{Binding Name}"></TextBlock>
            </HierarchicalDataTemplate>
        </TreeView.Resources>
    </TreeView>

</Window>

代码:

public partial class MainWindow : Window
{

    public MainWindow()
    {
        InitializeComponent();
    }

    public TreeViewModel TreeModel
    {
        get
        {
            return new TreeViewModel
            {
                Items = new ObservableCollection<NodeViewModel>{
                           new NodeViewModel { Name = "Root", Children =  new ObservableCollection<NodeViewModel> {
                              new NodeViewModel { Name = "Level1" ,  Children = new ObservableCollection<NodeViewModel>{ 
                                  new NodeViewModel{ Name = "Level2"}}} } }}
            };
        }
    }
}

public class TreeViewModel
{
    public ObservableCollection<NodeViewModel> Items { get; set; }
}

public class NodeViewModel
{
    public string Id { get; set; }
    public string Name { get; set; }
    public ObservableCollection<NodeViewModel> Children { get; set; }
}

结果:

enter image description here


是的,它有效。我确信以前尝试过了。非常感谢! - Mare Infinitus
嗨,谢谢分享。我使用了你的解决方案,但是它似乎不让我选择任何东西,而且左侧的箭头也不见了。树看起来像是被冻结了。我对你的代码做了一个更改,我将我的TreeModel从ViewModel类中绑定,而不是从MainWindow中绑定。 - Georgiana M
对我来说运行得很好。如果你想要传递而不是文本块的复选框,请参见https://dev59.com/m0vSa4cB1Zd3GeqPie8o。 - Chris

4
正如@sa_ddam213所说,您只需要HierarchicalDataTemplate用于NodeViewModel,但是您的代码唯一的问题是数据模板定义中DataType="x:Type local:TreeViewModel"缺少大括号({}) (它应该是DataType="{x:Type local:TreeViewModel}")。添加括号和ItemsSource绑定即可解决问题: TreeViewModel的附加HierarchicalDataTemplate未被使用,但不会造成任何影响。

你说得对,这确实是问题所在。奇怪的是,在ItemTemplate中使用时不需要大括号,但在Resources中却不行。 - Mare Infinitus
1
@MareInfinitus 这是因为在使用 ItemTemplate 时,不需要查看 DataType 属性。您直接告诉 TreeView 使用给定的模板来处理项。因此,不需要 DataType - Mohammad Dehghan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接