WPF TreeView with CheckBox - 如何获取选中的列表?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20800310/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 10:19:15  来源:igfitidea点击:

WPF TreeView with CheckBox - How to Get the list of Checked?

c#wpfcheckboxtreeview

提问by Tvd

I have implemented TreeView with Checkboxes from hereI shows perfectly well. Now I am wondering to get list of selected/checked items from the tree. I believe I need to code a recursive method. But the author has set the recursive method GetTree()to be Static and I can't get any clue to start the recursion. Similar article is also found here, I found in a way for my problem overe there also, but couldn't get any thing helpful.

我已经从这里实现了带有复选框的 TreeView, 我展示得非常好。现在我想知道从树中获取选定/选中项目的列表。我相信我需要编写一个递归方法。但是作者将递归方法GetTree()设置为Static,我找不到任何开始递归的线索。类似的文章也在这里找到,我在那里也找到了解决我的问题的方法,但没有得到任何有用的东西。

I am attaching whole code here for your reference :

我在这里附上整个代码供您参考:

    public class TreeViewModel : INotifyPropertyChanged
{
    public TreeViewModel(string name)
    {
        Name = name;
        Children = new List<TreeViewModel>();
    }

    #region Properties

    public string Name { get; private set; }
    public List<TreeViewModel> Children { get; private set; }
    public bool IsInitiallySelected { get; private set; }

    bool? _isChecked = false;
    TreeViewModel _parent;

    #region IsChecked

    public bool? IsChecked
    {
        get { return _isChecked; }
        set { SetIsChecked(value, true, true); }
    }

    void SetIsChecked(bool? value, bool updateChildren, bool updateParent)
    {
        if (value == _isChecked) return;

        _isChecked = value;

        if (updateChildren && _isChecked.HasValue) Children.ForEach(c => c.SetIsChecked(_isChecked, true, false));

        if (updateParent && _parent != null) _parent.VerifyCheckedState();

        NotifyPropertyChanged("IsChecked");
    }

    void VerifyCheckedState()
    {
        bool? state = null;

        for (int i = 0; i < Children.Count; ++i)
        {
            bool? current = Children[i].IsChecked;
            if (i == 0)
            {
                state = current;
            }
            else if (state != current)
            {
                state = null;
                break;
            }
        }

        SetIsChecked(state, false, true);
    }

    #endregion

    #endregion

    void Initialize()
    {
        foreach (TreeViewModel child in Children)
        {
            child._parent = this;
            child.Initialize();
        }
    }

    public static List<TreeViewModel> setTree(TreeViewModel tree)
    {
        List<TreeViewModel> treeView = new List<TreeViewModel>();
        treeView.Add(tree);
        tree.Initialize();

        return treeView;
    }

    public static List<TreeViewModel> SetTree(string topLevelName)
    {
        List<TreeViewModel> treeView = new List<TreeViewModel>();
        TreeViewModel tv = new TreeViewModel(topLevelName);

        treeView.Add(tv);

        //Perform recursive method to build treeview 

        #region Test Data
        //Doing this below for this example, you should do it dynamically 
        //***************************************************
        TreeViewModel tvChild4 = new TreeViewModel("Child4");

        tv.Children.Add(new TreeViewModel("Child1"));
        tv.Children.Add(new TreeViewModel("Child2"));
        tv.Children.Add(new TreeViewModel("Child3"));
        tv.Children.Add(tvChild4);
        tv.Children.Add(new TreeViewModel("Child5"));

        TreeViewModel grtGrdChild2 = (new TreeViewModel("GrandChild4-2"));

        tvChild4.Children.Add(new TreeViewModel("GrandChild4-1"));
        tvChild4.Children.Add(grtGrdChild2);
        tvChild4.Children.Add(new TreeViewModel("GrandChild4-3"));

        grtGrdChild2.Children.Add(new TreeViewModel("GreatGrandChild4-2-1"));
        //***************************************************
        #endregion

        tv.Initialize();

        return treeView;
    }

    public static List<string> GetTree()
    {
        List<string> selected = new List<string>();

        //select = recursive method to check each tree view item for selection (if required)

        return selected;

        //***********************************************************
        //From your window capture selected your treeview control like:   TreeViewModel root = (TreeViewModel)TreeViewControl.Items[0];
        //                                                                List<string> selected = new List<string>(TreeViewModel.GetTree());
        //***********************************************************
    }

    #region INotifyPropertyChanged Members

    void NotifyPropertyChanged(string info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    #endregion
}

I couldn't find appropriate to se the tree dynamically from my code using SetTree(string topLevelName)method, hence I added setTree(TreeViewModel tree)method to suit my needs.

我找不到合适的SetTree(string topLevelName)方法从我的代码中使用方法动态地设置树,因此我添加了setTree(TreeViewModel tree)方法来满足我的需要。

Can anyone please help me to implement GetTree() method to get list of items that is checked. If an item of the tree is selected, the TreeViewModel's IsChecked property is set to true. So IsChecked can be used to find if the item is selected r not.

任何人都可以帮我实现 GetTree() 方法来获取检查的项目列表。如果选择了树的一项,则 TreeViewModel 的 IsChecked 属性设置为 true。因此 IsChecked 可用于查找项目是否被选中。

回答by Chris Badman

To get all checked node in your tree below and includinga certain node, call the following GetCheckedItemsmethod on that node:

要在下面的树获取所有选中的节点并包括某个节点,请在该节点上调用以下GetCheckedItems方法:

private IEnumerable<TreeViewModel> GetCheckedItems(TreeViewModel node)
{
    var checkedItems = new List<TreeViewModel>();

    ProcessNode(node, checkedItems);

    return checkedItems;
}    

private void ProcessNode(TreeViewModel node, IEnumerable<TreeViewModel> checkedItems)
{
    foreach (var child in node.Children)
    {
        if (child.IsChecked)
            checkedItems.Add(child);

        ProcessNode(child, checkedItems);
    }
}