在树形视图MVVM中获取父项

问题描述 投票:0回答:1

我试着用treeview base one MVVM学习。我参考了这个教程 https:/www.codeproject.comArticles26288Simplifying-the-WPF-TreeView-by-Using-the-ViewMode

这是非常有帮助的,我试图通过重写代码来理解它。

TreeViewViewModel.cs

public class TreeViewViewModel
{
    private ObservableCollection<TreeNode> _firstNode;
    public static TreeNode _seletectedNode;
    private ObservableCollection<TreeNode> _node;

    private ICommand _addCommand;

    public TreeViewViewModel(TreeNode rootNode) : this(rootNode, null) {}

    public TreeViewViewModel(TreeNode rootNode, TreeViewViewModel parentNode)
    {
        _firstNode = new ObservableCollection<TreeNode>(rootNode.Node);
        _node = new ObservableCollection<TreeNode>((from child in rootNode.Node select child).ToList<TreeNode>());

        _addCommand = new AddCommand(this);
    }

    public ObservableCollection<TreeNode> FirstNode
    {
        get { return _firstNode; }
        set { _firstNode = value; }
    }

    public ObservableCollection<TreeNode> Node
    {
        get { return _node; }
        set { _node = value; }
    }

    public TreeNode Selected
    {
        get{ return _seletectedNode; }
        set{ _seletectedNode = value;}
    }

    public ICommand AddCommand
    {
        get { return _addCommand; }
    }
}

树节点.cs

public class TreeNode : INotifyPropertyChanged
{
    private ObservableCollection<TreeNode> _Node = new ObservableCollection<TreeNode>();

    private string _Name;
    private string _ID;

    private bool _isExpanded;
    private bool _isSelected;

    public ObservableCollection<TreeNode> Node
    {
        get { return _Node; }
        set
        {
            _Node = value;
            OnPropertyChanged("Node");
        }
    }

    public string Name
    {
        get { return _Name; }
        set { _Name = value; OnPropertyChanged("Name"); }
    }

    public string ID
    {
        get { return _ID; }
        set { _ID = value; OnPropertyChanged("ID");}
    }

    public bool IsExpanded
    {
        get { return _isExpanded; }
        set
        {
            if (value != _isExpanded)
            {
                _isExpanded = value;
                this.OnPropertyChanged("IsExpanded");
            }
        }
    }   

    public bool IsSelected
    {
        get { return _isSelected; }
        set
        {
            if (value != _isSelected)
            {
                _isSelected = value;
                this.OnPropertyChanged("IsSelected");

                if (_isSelected) {TreeViewViewModel._seletectedNode = this;}
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

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

}

AddCommand.cs

public class AddCommand : ICommand
{
    private TreeViewViewModel _TreeView;

    public AddCommand(TreeViewViewModel treeView)
    {
        _TreeView = treeView;
    }

    public event EventHandler CanExecuteChanged;

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public void Execute(object parameter)
    {
        //Show Selected item
        //MessageBox.Show(_TreeView.Selected.Name);

        //Add first level item
        //_TreeView.FirstNode.Add(new TreeNode { Name = "Hihi" });

        //Rename selected item
        //_TreeView.Selected.Name = "Hello";

        //Remove first level item
        //_TreeView.FirstNode.Remove(_TreeView.Selected);

        //Add selected item
        //_TreeView.Selected.Node.Add(new TreeNode { Name = "Hihi" });

    }
}

主窗口.xaml.cs。

public partial class MainWindow : Window
{
    public TreeViewViewModel _TreeView;

    public MainWindow()
    {
        InitializeComponent();

        TreeNode rootNode = new TreeNode
        {
            Name = "David",
            Node =
            {
                new TreeNode
                {
                    Name = "Alberto",
                    Node =
                    {
                        new TreeNode
                        {
                            Name = "Zena",
                            Node =
                            {
                                new TreeNode
                                {
                                    Name = "Nick",
                                }
                            }
                        },
                        new TreeNode
                        {
                            Name = "Sarah",
                        },
                    }
                },
                new TreeNode
                {
                    Name = "Komrade",
                }
            }
        };


        _TreeView = new TreeViewViewModel(rootNode);

        base.DataContext = _TreeView;
    }
}

主窗口.xaml

<Window x:Class="TreeviewMVVM_Test.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TreeviewMVVM_Test"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>

        <TextBox Margin="10,35,380,260"/>

        <Button Margin="154,27,324,268"  Command="{Binding AddCommand}" />



        <TreeView x:Name="treeView"
                            ItemsSource="{Binding FirstNode}" 
                            BorderThickness="0"
                            Height="Auto" Width="Auto"
                            Margin="21,84,349,19">

            <TreeView.ItemContainerStyle>
                <Style TargetType="{x:Type TreeViewItem}" BasedOn="{StaticResource {x:Type TreeViewItem}}">
                    <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
                    <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
                    <Setter Property="FontWeight" Value="Normal" />
                    <Style.Triggers>
                        <Trigger Property="IsSelected" Value="True">
                            <Setter Property="FontWeight" Value="Bold" />
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </TreeView.ItemContainerStyle>

            <TreeView.ItemTemplate>
                <HierarchicalDataTemplate ItemsSource="{Binding Node}">
                    <TextBlock Text="{Binding Name}" />
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>
        </TreeView>
    </Grid>
</Window>

我的源代码工作正常,我可以从选定的节点中添加子节点,删除一级节点,重命名选定节点,获取选定节点。但是只有一点,我不知道如何存储和获取父节点。

我看了Josh的教程,好像是父节点存储在contructor中。下面是Josh的代码。如果我使用这样的代码,父节点是一个TreeViewViewModel,而不是一个节点。我不想这样,有什么办法可以让父节点变成TreeNode类型。我想使用这样的_treeView.Seletect.Parent.Name,它应该打印所选节点的父节点名。

    private PersonViewModel(Person person, PersonViewModel parent)
    {
        _person = person;
        _parent = parent;
        _children = new ObservableCollection<PersonViewModel>(
                (from child in _person.Children
                 select new PersonViewModel(child, this))
                 .ToList<PersonViewModel>());
    }
c# wpf mvvm treeviewitem
1个回答
2
投票

父节点不应该是一个 TreeViewViewModel,它应该是一个 TreeNode.

您的 TreeNode 是相当于乔希的 PersonViewModel.

在乔希的世界里

Person 是模型(数据)

PersonViewModel 是该数据以树项形式呈现的表示。

PersonViewModel 构造函数需要两个参数。要显示的数据 (Person),以及对父树项的引用(PersonViewModel). 然后,构造函数创建所有的子树项 (PersonViewModel),通过迭代数据的子项。(Person)

在你的世界里。

?? 是模型(没有任何模型)

TreeNode 是一些数据的表示,其名称和ID被呈现为树项。换句话说,TreeNode既是模型又是视图模型(这不一定是错的)。

然而,你试图在视图中构建数据,这是错误的。你也在构造你的树 倒退,从叶子到根。由于你是先构造子代,你不能设置父代,因为父代在这时并不存在。

在Josh的世界里,层次结构已经存在于模型中,所以父代是可用的。如果你同时构建modelVM,你需要用不同的方式构建你的树,以便在创建子代之前,父代就已经存在了。

© www.soinside.com 2019 - 2024. All rights reserved.