TreeView、HierarchicalDataTemplate 和递归数据

TreeView, HierarchicalDataTemplate and recursive Data
2021-11-25
  •  译文(汉语)
  •  原文(英语)

对于我的树视图,我有两个不同的类提供 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作为ItemsSourceTreeView.如果显示任何内容,它不会分层显示数据.

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

它有什么问题?

也许问题是第一个TextBlock Text Binding?我想在那里显示Name属性.NodeViewModelItems

解决过程1

正如@ sa_ddam213说,你只需要HierarchicalDataTemplateNodeViewModel,但你的代码的唯一问题是缺少括号({})为DataType="x:Type local:TreeViewModel"您的数据模板定义(应该是DataType="{x:Type local:TreeViewModel}").添加括号和ItemsSource绑定解决问题:

不使用附加的HierarchicalDataTemplatefor TreeViewModel,但它不会造成伤害.

解决过程2

您应该只需要声明HierarchicalDataTemplateforNodeViewModel因为这是在 中显示的唯一内容TreeView,并将实际绑定ItemSourceTreeView

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

完整示例

Xml:

<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; }
}

结果:

TreeView、HierarchicalDataTemplate 和递归数据

For my treeview I have two different classes that provide the 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; }
}

Now I want my TreeView to display the Items in TreeViewModel and show hierarchical data as provided by the NodeViewModel.

Here is my 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>

Have tried to provide Items as the ItemsSource of the TreeView. It does not show the data hierarchically, if displaying anything.

And I tried using the ItemTemplate instead of the TreeView.Resources, too.

What is wrong about it?

Perhaps a problem is the first TextBlock Text Binding? I want to display the Name property of the NodeViewModel in Items there.

Solutions1

As @sa_ddam213 said, you only need the HierarchicalDataTemplate for NodeViewModel, but the only problem with your code was the missing braces ({ and }) for DataType="x:Type local:TreeViewModel" in your data template definitions (it should be DataType="{x:Type local:TreeViewModel}"). Adding brackets and ItemsSource binding solves the problem:

The additional HierarchicalDataTemplate for TreeViewModel is not used, but it does not harm.

Solutions2

You should only have to declare the HierarchicalDataTemplate for NodeViewModel as this is the only thing showing in the TreeView, and bind the actual ItemSource to the 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>

Full Example

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>

Code:

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; }
}

Result:

TreeView, HierarchicalDataTemplate and recursive Data

转载于:https://stackoverflow.com/questions/15240326/treeview-hierarchicaldatatemplate-and-recursive-data

本人是.net程序员,因为英语不行,使用工具翻译,希望对有需要的人有所帮助
如果本文质量不好,还请谅解,毕竟这些操作还是比较费时的,英语较好的可以看原文

留言回复
我们只提供高质量资源,素材,源码,坚持 下了就能用 原则,让客户花了钱觉得值
上班时间 : 周一至周五9:00-17:30 期待您的加入