在objectlistview treelistview中查找父级

时间:2015-03-22 10:11:27

标签: c# objectlistview

当使用objectListView treeListView时,如果我已经扩展了treeListView并且点击了其中一列中的一个子节点,我该怎么做:

  1. 找到那个孩子的父母?
  2. 查找已展开的列的父行的值/文本?
  3. 这个例子可能有助于解释我的意思。

    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中父级的值。

2 个答案:

答案 0 :(得分:2)

通过添加简单的double值作为子项,您自己做得有点困难。那些项目缺乏找到真正父母的潜力。

如果您能够更改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
        }
    }
}

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

答案 1 :(得分: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