C# 在objectlistview树视图中查找父级

C# 在objectlistview树视图中查找父级,c#,objectlistview,C#,Objectlistview,使用objectListView treeListView时,如果我已展开treeListView并单击其中一列中的一个子项,我如何: 找到那个孩子的父母了吗 是否查找展开列的父行的值/文本 这个例子可能有助于解释我的意思 public partial class Form1 : Form { List<Contract> list; public Form1() { InitializeComponent(); list

使用objectListView treeListView时,如果我已展开treeListView并单击其中一列中的一个子项,我如何:

  • 找到那个孩子的父母了吗
  • 是否查找展开列的父行的值/文本
  • 这个例子可能有助于解释我的意思

    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);
        }
    }
    
    公共部分类表单1:表单
    {
    名单;
    公共表格1()
    {
    初始化组件();
    列表=新列表();
    增加(新合同(“A”,1));
    增加(新合同(“B”,2));
    foreach(列表中的合同c)
    {
    this.treeListView1.CanExpandGetter=委托(对象x)
    {
    如果(x是合同)
    {
    返回(((合同)x).Children.Count>0);
    }
    其他的
    {
    返回false;
    }
    };
    this.treeListView1.ChildrenGetter=委托(对象x)
    {
    合同合同=x作为合同;
    返回合同儿童;
    };
    column1.AspectGetter=委托(对象x)
    {
    如果(x是合同)
    {
    退货((合同)x).名称;
    }
    其他的
    {
    返回“”;
    }
    };
    column2.AspectGetter=委托(对象x)
    {
    如果(x是合同)
    {
    退货((合同)x).价值;
    }
    其他的
    {
    双d=(双)x;
    返回d.ToString();
    }
    };
    this.treeListView1.AddObject(c);
    }
    }
    私有void树列表视图1\u单元格单击(对象发送者,BrightIdeasSoftware.CellClickEventArgs e)
    {
    //我不知道该怎么办
    }
    公共无效写线(字符串s)
    {
    如果(this.richTextBox1.TextLength>0)
    {
    this.richTextBox1.AppendText(Environment.NewLine);
    }
    此.richTextBox1.AppendText;
    }
    }
    公共类合同
    {
    公共字符串名称{get;set;}
    公共双值{get;set;}
    公共列表子项{get;set;}
    公共合同(字符串名称,双值)
    {
    名称=名称;
    价值=价值;
    Children=新列表();
    增加(2);
    增加(3);
    }
    }
    

    在CellClick事件中,我想获取父项和第1列中父项的任何值。

    通过添加简单的双值作为子项,您自己也有点困难。这些物品没有潜力让你找到真正的父母

    如果您能够更改合同类,则可以将其更改为TreeNode类型,其子类始终引用合同本身。单击cell_后,您可以简单地获取e.模型,然后获取父对象,以防它本身不是合同

    如果您想让它在将来的实现中更加灵活,那么您可以以符合树结构的方式更改契约

    一个表示节点有子节点的接口

    public interface ITreeNode
    {
        IList<ITreeChild> Children { get; }
    }
    
    使子项中的父引用保持最新的根节点

    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;
            }
        }
    }
    
    一个非常基本的树冠(更多的是用作测试)

    然后最终你的合同

    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;
            }
        }
    }
    
    然后构建树状结构视图:

    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
            }
        }
    }
    

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

    通过添加简单的双值作为子项,您自己也有点困难。这些物品没有潜力让你找到真正的父母

    如果您能够更改合同类,则可以将其更改为TreeNode类型,其子类始终引用合同本身。单击cell_后,您可以简单地获取e.模型,然后获取父对象,以防它本身不是合同

    如果您想让它在将来的实现中更加灵活,那么您可以以符合树结构的方式更改契约

    一个表示节点有子节点的接口

    public interface ITreeNode
    {
        IList<ITreeChild> Children { get; }
    }
    
    使子项中的父引用保持最新的根节点

    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;
            }
        }
    }
    
    一个非常基本的树冠(更多的是用作测试)

    然后最终你的合同

    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;
            }
        }
    }
    
    然后构建树状结构视图:

    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
            }
        }
    }
    

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

    这是在VB.net中,但我刚刚找到了一个非常简单的解决方案。只需调用treelistview.getparent事件。我的示例在format row事件中显示了它,但您也可以在selected item事件中使用它。希望这有帮助

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

    这是在VB.net中,但我刚刚找到了一个非常简单的解决方案。只需调用treelistview.getparent事件。我的示例在format row事件中显示了它,但您也可以在selected item事件中使用它。希望这有帮助

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

    这是一种可行的方法,我同意,如果没有其他解决方案,我认为这将是向前推进的最佳方法,以您的方式编写它是非常有意义的,因此是向上投票。但是,我认为一定有一种方法可以通过objectlistview实现。也许有人可以添加他们的想法。CellClickEventArg确实有一个被点击的行索引,但是,除了选择
    e.ListView.TreeModel.GetNthObject(e.RowIndex)
    我发现还有很多事情可以做(我也没有下载api)是的,我尝试了rowIndex,但这取决于您的父级