在objectlistview treelistview中找到parent

Find the parent in objectlistview treelistview

使用 objectListView treeListView 时,如果我展开了 treeListView 并单击了其中一列中的 children 之一,我该如何:

  1. 找到那个 child 的 parent?
  2. 查找已展开列的 parent 行的 value/text?

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

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 事件中,我想同时获得 parent 以及 column1 中 parent 的任何值。

您通过将简单的双精度值添加为 child 项,让自己变得有点困难。这些项目缺乏让您找到真正的潜力 parent.

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

如果你想让它在你想要制作的未来实现中更加灵活,你可以以符合树结构的方式更改合约

一个接口说你的节点有 children

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

一个界面说它有一个 parent

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

使 child 项中的 parent 引用保持最新的根节点

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

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

这在 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