在objectlistview treelistview中找到parent
Find the parent in objectlistview treelistview
使用 objectListView treeListView 时,如果我展开了 treeListView 并单击了其中一列中的 children 之一,我该如何:
- 找到那个 child 的 parent?
- 查找已展开列的 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
使用 objectListView treeListView 时,如果我展开了 treeListView 并单击了其中一列中的 children 之一,我该如何:
- 找到那个 child 的 parent?
- 查找已展开列的 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