【问题标题】:Find the parent in objectlistview treelistview在 objectlistview treelistview 中查找父级
【发布时间】:2015-03-22 10:11:27
【问题描述】:

在使用 objectListView treeListView 时,如果我展开了 treeListView 并单击了其中一列中的一个子项,我该怎么做:

  1. 找到那个孩子的父母?
  2. 查找已展开列的父行的值/文本?

这个例子可能有助于解释我的意思。

public partial class Form1 : Form
{

    List<Contract> list;
    public Form1()
    {
        InitializeComponent();

        list = new List<Contract>();
        list.Add(new Contract("A", 1));
        list.Add(new Contract("B", 2));
        foreach (Contract c in list)
        {
            this.treeListView1.CanExpandGetter = delegate(object x)
            {
                if (x is Contract)
                {
                    return (((Contract)x).Children.Count > 0);
                }
                else
                {
                    return false;
                }
            };
            this.treeListView1.ChildrenGetter = delegate(object x)
            {
                Contract contrat = x as Contract;
                return contrat.Children;
            };

            column1.AspectGetter = delegate(object x)
            {
                if (x is Contract)
                {
                    return ((Contract)x).Name;
                }
                else
                {
                    return " ";
                }
            };

            column2.AspectGetter = delegate(object x)
            {
                if (x is Contract)
                {
                    return ((Contract)x).Value;
                }
                else
                {
                    Double d = (Double)x;
                    return d.ToString();
                }
            };

            this.treeListView1.AddObject(c);
        }
    }

    private void treeListView1_CellClick(object sender, BrightIdeasSoftware.CellClickEventArgs e)
    {
         //NOT SURE WHAT TO DO HERE

    }

    public void WriteLine(String s)
    {
        if (this.richTextBox1.TextLength > 0)
        {
            this.richTextBox1.AppendText(Environment.NewLine);
        }
        this.richTextBox1.AppendText(s);
    }
}

public class Contract
{
    public string Name { get; set;}
    public Double Value { get; set; }
    public List<Double> Children {get; set;}

    public Contract(string name, Double value)
    {
        Name = name;
        Value = value;
        Children = new List<Double>();
        Children.Add(2);
        Children.Add(3);
    }
}

在 CellClick 事件中,我想同时获取父级和 column1 中父级的值。

【问题讨论】:

    标签: c# objectlistview


    【解决方案1】:

    通过添加简单的双精度值作为子项,您自己有点困难。这些项目缺乏让你找到真正父母的潜力。

    如果您能够更改您的 Contract 类,您可以将其更改为 TreeNode 类型,其子项始终引用合同本身。在 cell_click 上,您可以简单地获取 e.Model,然后获取父级,以防它本身不是合约。

    如果你想让它在你想要实现的未来实现中更加灵活,你可以改变契约,使其符合树形结构

    表示您的节点有子节点的接口

    public interface ITreeNode
    {
        IList<ITreeChild> Children { get; }
    }
    

    表示它有父级的接口

    public interface ITreeChild
    {
        object Parent { get; set; }
    }
    

    使 childItems 中的父引用保持最新的根节点

    public abstract class TreeRoot : ITreeNode, IDisposable
    {
        private readonly IList<ITreeChild> children = new ObservableCollection<ITreeChild>();
        public IList<ITreeChild> Children
        {
            get
            {
                return children;
            }
        }
    
        protected virtual void OnChildCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.OldItems != null)
            {
                foreach (var item in e.OldItems)
                {
                    var treeItem = item as ITreeChild;
                    if (treeItem == null)
                    {
                        continue;
                    }
                    treeItem.Parent = null;
                }
            }
            if (e.NewItems != null)
            {
                foreach (var item in e.NewItems)
                {
                    var treeItem = item as ITreeChild;
                    if (treeItem == null)
                    {
                        continue;
                    }
                    treeItem.Parent = this;
                }
            }
        }
    
        private bool isDisposed = false;
        public virtual void Dispose(bool disposing)
        {
            if (!disposing)
            {
                return;
            }
            if (isDisposed)
            {
                return;
            }
            isDisposed = true;
            Destroy();
        }
    
        public void Dispose()
        {
            Dispose(true);
        }
    
        public void Init()
        {
            var colc = Children as INotifyCollectionChanged;
            if (colc != null)
            {
                colc.CollectionChanged += OnChildCollectionChanged;
            }
        }
    
        public void Destroy()
        {
            Children.Clear();
            var colc = Children as INotifyCollectionChanged;
            if (colc != null)
            {
                colc.CollectionChanged -= OnChildCollectionChanged;
            }
        }
    }
    

    还有一个基于这个 TreeRoot 的 TreeNode

    public class TreeNode : TreeRoot, ITreeChild
    {
        public string Name
        {
            get;
            set;
        }
    
        private object parent;
        public object Parent
        {
            get
            {
                return parent;
            }
            set
            {
                parent = value;
            }
        }
    
        public TreeNode()
            : base()
        {
            Init();
        }
    }
    

    一个非常基本的TreeChild(它更多地被用作测试)

    public class TreeChild : ITreeChild
    {
        public object Parent
        {
            get;set;
        }
    }
    

    然后是你的合同

    public class Contract : TreeNode
    {
        public Double Value { get; set; }
    
        public Contract()
            : base()
        {
        }
    }
    

    它可以包含各种ITreeChild,所以让它成为一个DoubleChild

    public class DoubleChild : TreeChild
    {
        private double value;
        public double Value
        {
            get
            {
                return value;
            }
            set
            {
                this.value = value;
            }
        }
    }
    

    然后构造你的 TreeListView:

    protected void AddDefault(TreeNode c)
    {
        c.Children.Add(new DoubleChild { Value = 3 });
        c.Children.Add(new DoubleChild { Value = 4 });
    }
    
    TreeListView treeListView1;
    
    public Form1()
    {
        InitializeComponent();
        treeListView1 = new TreeListView();
        treeListView1.CellClick += treeListView1_CellClick;
        OLVColumn columnName = new OLVColumn();
        columnName.AspectGetter = (obj) =>
        {
            var node = obj as TreeNode;
            if (node != null)
            {
                return node.Name;
            }
            return " ";
        };
        OLVColumn columnValue = new OLVColumn("Value", "Value");
        treeListView1.Columns.Add(columnName);
        treeListView1.Columns.Add(columnValue);
        TreeNode rootContract = new TreeNode() { Name = "All Contracts" };
        Contract childContract1 = new Contract() { Name = "A", Value = 2 };
        Contract childContract2 = new Contract() { Name = "B", Value = 3 };
        AddDefault(childContract1);
        AddDefault(childContract2);
        rootContract.Children.Add(childContract1);
        rootContract.Children.Add(childContract2);
        AddDefault(rootContract);
        treeListView1.ParentGetter = (obj) =>
        {
            var child = obj as ITreeChild;
            if (child == null)
            {
                return null;
            }
            return child.Parent;
        };
        treeListView1.ChildrenGetter = (obj) =>
        {
            var child = obj as ITreeNode;
            if (child == null)
            {
                return null;
            }
            return child.Children;
        };
    
        treeListView1.CanExpandGetter = (obj) =>
        {
            return obj is ITreeNode && ((ITreeNode)obj).Children.Count > 0;
        };
    
        treeListView1.AddObject(rootContract);
        treeListView1.Dock = DockStyle.Fill;
        this.Controls.Add(treeListView1);
    }
    
    void treeListView1_CellClick(object sender, CellClickEventArgs e)
    {
        if (e.Model is Contract)
        {
            // you selected a contract
        }
        else
        {
            var tree = e.Model as ITreeChild;
            var parent = tree.Parent;
            if (parent is Contract)
            {
                // selected contract
            }
            else
            {
                // rootnode
            }
        }
    }
    

    我知道,这可能需要更多的工作(我也可能让它有点复杂,不知道库),但这应该适用于您的用例

    【讨论】:

    • 我同意这是一种可能的方式,如果没有其他解决方案,认为这将是前进的最佳方式,按照您的方式编写它很有意义完成,因此赞成。但是,我认为必须有一种方法可以通过objectlistview来做到这一点。也许有这方面工作知识的人可以添加他们的想法。
    • CellClickEventArgs 确实有一个被点击的 RowIndex,但是,除了选择 e.ListView.TreeModel.GetNthObject(e.RowIndex) 之外,我发现有很多是可行的(我也没有下载 api)
    • 是的,我尝试了 rowIndex,但这取决于您扩展的父级。
    【解决方案2】:

    这是在 VB.net 中,但我刚刚找到了一个非常简单的解决方案。只需调用 treelistview.getparent 事件。我的示例在格式行事件中显示它,但您也可以在选定项目事件中使用它。希望这会有所帮助

    Private Sub TreeListView1_FormatRow(sender As Object, e As FormatRowEventArgs) Handles TreeListView1.FormatRow
    
            Dim parent As myObjectExample = TreeListView1.GetParent(e.Model)
    
    End Sub
    

    【讨论】:

    • 我更喜欢这种方法,因为它打字少:)
    猜你喜欢
    • 2013-01-31
    • 2014-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-24
    • 2014-12-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多