使用MVVM构建TreeView的XAML定义

时间:2017-06-16 02:44:17

标签: c# wpf xaml mvvm treeview

我试图在MVVM应用中使用WPF构建TreeView,但我不了解如何处理HierarchicalDataTemplate。我的TreeView应该代表一个文件夹结构,其中包含文件夹中的文件夹等等。

我的文件夹ViewModel定义如下:

public class TreeViewFolderViewModel : ViewModelBase
{
    private int _id;
    private int _parentId;
    private string _text;
    private string _key;
    private ObservableCollection<TreeViewFolderViewModel> _children;

    public int Id
    {
        get { return this._id; }
        set { Set(() => Id, ref this._id, value); }
    }

    public int ParentId
    {
        get { return this._parentId; }
        set { Set(() => ParentId, ref this._parentId, value); }
    }

    public string Text
    {
        get { return this._text; }
        set { Set(() => Text, ref this._text, value); }
    }

    public string Key
    {
        get { return this._key; }
        set { Set(() => Key, ref this._key, value); }
    }

    public ObservableCollection<TreeViewFolderViewModel> Children
    {
        get { return this._children ?? (this._children = 
              new ObservableCollection<TreeViewFolderViewModel>()); }
        set { Set(() => Children, ref this._children, value); }
    }
}

我的模型与我的ViewModel具有相同的结构,因此最终的ViewModel是包含子文件夹的文件夹列表,依此类推。我使用递归加载所有这些文件夹,那部分工作正常。

我遇到的问题是如何定义ViewModel并将其加载到实际的TreeView中。

我已经阅读了socket.io,而我或多或少地了解了正在发生的事情,但TreeView的每个级别代表了不同的对象类型,而我的{{{} 1}}只有一种对象类型,我对如何定义它感到困惑。

我的MainWindowViewModel中的根TreeView属性是ViewModel类型,这意味着我有一个对象代表我的TreeView的根。此对象具有TreeViewFolderViewModel类型的子级,而这些子级又具有TreeViewFolderViewModel类型的子级,等等

我如何在TreeViewFolderViewModel中定义此内容?我有以下定义:

XAML

我的<TreeView Grid.Row="1" Margin="5,0,5,5" ItemsSource="{Binding RootFolder}"/> 模板定义如下:

Hierarchical

但是没有任何东西在加载。

关于我如何解决这个问题的任何想法?

感谢。

1 个答案:

答案 0 :(得分:1)

我准备了一个小样本来说明。

<强>的ViewModels

public class TreeViewFolderViewModel : ViewModelBase
{
    private int id;
    public int Id
    {
        get { return id; }
        set { id = value; OnPropertyChanged("Id"); }
    }

    private string text;
    public string Text
    {
        get { return text; }
        set { text = value; OnPropertyChanged("Text"); }
    }

    private ObservableCollection<TreeViewFolderViewModel> children;
    public ObservableCollection<TreeViewFolderViewModel> Children
    {
        get
        {
            return children ?? (children =
            new ObservableCollection<TreeViewFolderViewModel>());
        }
        set { children = value; OnPropertyChanged("Children"); }
    }
}

public class TreeViewModel : ViewModelBase
{
    private List<TreeViewFolderViewModel> items;
    public List<TreeViewFolderViewModel> Items
    {
        get { return items; }
        set { items = value; OnPropertyChanged("Items"); }
    }

    public TreeViewModel()
    {
        Items = new List<TreeViewFolderViewModel>()
        {
            new TreeViewFolderViewModel()
            {
                Id =0, Text="RootFolder", Children=new ObservableCollection<TreeViewFolderViewModel>()
                {
                    new TreeViewFolderViewModel() { Id = 10, Text = "FirstFolder", Children=new ObservableCollection<TreeViewFolderViewModel>() { new TreeViewFolderViewModel() { Id = 11, Text = "FirstChild" } } } ,
                    new TreeViewFolderViewModel() { Id = 20, Text = "SecondFolder", Children = new ObservableCollection<TreeViewFolderViewModel>() { new TreeViewFolderViewModel() { Id = 21, Text = "SecondChild" } } } ,
                    new TreeViewFolderViewModel() { Id = 30, Text = "ThirdFolder", Children = new ObservableCollection<TreeViewFolderViewModel>() { new TreeViewFolderViewModel() { Id = 31, Text = "ThirdChild" } } }
                }
            }
        };
    }
}

public class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
    }
}

<强> MainWindow.xaml

<Window x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApp"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <local:TreeViewModel />
    </Window.DataContext>

    <Window.Resources>    
        <HierarchicalDataTemplate ItemsSource="{Binding Children}" 
                                  DataType="{x:Type local:TreeViewFolderViewModel}">
            <TextBlock>
                <TextBlock.Text>
                    <MultiBinding StringFormat="{}{0} {1}">
                        <Binding Path="Id" />
                        <Binding Path="Text" />
                    </MultiBinding>
                </TextBlock.Text>
            </TextBlock>
        </HierarchicalDataTemplate>    
    </Window.Resources>

    <Grid>
        <TreeView ItemsSource="{Binding Items}" />
    </Grid>
</Window>