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