如何将TreeViewItems添加到TreeView控件

时间:2013-07-31 14:38:01

标签: c# wpf mvvm treeview

此问题是this问题的后续问题。我从这个网站上得到了一些建议,并决定开始学习MVVM实现我的TreeViews工作。有了这个说,我对MVVM非常新,我仍然熟悉语法和实现。

我有一个显示整数类型数据的TreeView,但我希望它能用于字符串。该树还允许用户通过选择TreeViewItem然后在textBox中键入新的整数标题,然后单击按钮来添加到任何级别。

Example Image

我希望父母,孩子和孙子在启动时可以使用预定义的名字。另外需要注意的是,该用户只能在子级别添加到TreeView(因此他们只能添加孙子)。

模型

public class TreeViewModel : PropertyChangedBase
{
    public string Value { get; set; }

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

    public CollectionView ItemsView { get; set; }

    public TreeViewModel(string value)
    {
        Items = new ObservableCollection<TreeViewModel>();
        ItemsView = new ListCollectionView(Items)
        {
            SortDescriptions =
            {
                new SortDescription("Value",ListSortDirection.Ascending)
            }
        };
        Value = value;
    }
}

视图模型

public class SortedTreeViewWindowViewModel : PropertyChangedBase
{
    private string _newValueString;

    public string NewValueString
    {
        get { return _newValueString; }
        set
        {
            _newValueString = value;

            OnPropertyChanged("NewValueString");
        }
    }

    public TreeViewModel SelectedItem { get; set; }

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

    public ICollectionView ItemsView { get; set; }

    public SortedTreeViewWindowViewModel()
    {
        Items = new ObservableCollection<TreeViewModel>();
        ItemsView = new ListCollectionView(Items) { SortDescriptions = { new SortDescription("Value", ListSortDirection.Ascending) } };
    }

    public void AddNewItem()
    {
        ObservableCollection<TreeViewModel> targetcollection;

        //Insert the New Node as a Root node if nothing is selected.
        targetcollection = SelectedItem == null ? Items : SelectedItem.Items;

        if (_newValueString != null)
        {
            targetcollection.Add(new TreeViewModel(_newValueString));
            NewValueString = string.Empty;
        }
    }
}

查看代码隐藏

public partial class Window1 : Window
{
    public SortedTreeViewWindowViewModel ViewModel { get { return DataContext as SortedTreeViewWindowViewModel; } set { DataContext = value; } }

    public Window1()
    {
        InitializeComponent();
        ViewModel = new SortedTreeViewWindowViewModel()
            {
                Items = {new TreeViewModel("Test")}
            };
    }

    private void AddNewItem(object sender, RoutedEventArgs e)
    {
        ViewModel.AddNewItem();
    }

    private void OnSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
    {
        ViewModel.SelectedItem = e.NewValue as TreeViewModel;
    }
}

非常感谢你的帮助。我希望通过这个将有助于我了解如何编辑和构建ViewModel,以便我可以学习将来即兴创作。

更新

TreeView现在由字符串组成,因此该部分已解决。我仍然需要有关默认节点的帮助。我已更新我的代码以反映此更改。

1 个答案:

答案 0 :(得分:3)

以下是我的建议

  • 将您拥有int的位置更改为string。 TreeView应该处理这种变化。
  • 在ViewModel的构造函数中,手动插入默认节点。确保您了解如何使用TreeView,因为这会影响Model和ViewModel的设计,并自然地改进实现。

这是一个非常简单的示例,如何填充ViewModel中的树,该树绑定到视图中的TreeView:

查看

<Window x:Class="TreeViewExample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <StackPanel>
            <TreeView ItemsSource="{Binding Tree}"/>
        </StackPanel>
    </StackPanel>
</Window>

查看代码隐藏

namespace TreeViewExample
{
    using System.Windows;

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            DataContext = new MainWindowViewModel();
            InitializeComponent();
        }
    }
}

<强>视图模型

namespace TreeViewExample
{
    using System.Collections.ObjectModel;
    using System.Windows.Controls;

    class MainWindowViewModel
    {
        public ObservableCollection<TreeViewItem> Tree { get; set; }

        public MainWindowViewModel()
        {
            Tree = new ObservableCollection<TreeViewItem>();
            Tree.Add(GetLoadedTreeRoot());
        }

        private TreeViewItem GetLoadedTreeRoot()
        {
            TreeViewItem parent = new TreeViewItem() { Header = "Parent" };
            TreeViewItem child1 = new TreeViewItem() { Header = "Child 1" };
            TreeViewItem child2 = new TreeViewItem() { Header = "Child 2" };
            TreeViewItem grandchild1 = new TreeViewItem() { Header = "Grandchild 1" };
            TreeViewItem grandchild2 = new TreeViewItem() { Header = "Grandchild 2" };

            child1.Items.Add(grandchild1);
            child2.Items.Add(grandchild2);
            parent.Items.Add(child1);
            parent.Items.Add(child2);
            return parent;
        }
    }
}

产地:

    • 孩子1
      • 孙子1
    • 孩子2
      • 孙子2

其他想法:

  • 要清理代码隐藏,您可能会查找一个Command实现,其中有很多。虽然有时需要它,但尽可能避免代码隐藏中的代码。我非常喜欢this example因为它向您展示了一般的MVVM实现,而没有进入与高级命令相关的主题(ItemTemplates,Interactivity命名空间等)。