ObjectListView - TreeListView Auto TriStateChecking
本文关键字:TriStateChecking Auto TreeListView ObjectListView | 更新日期: 2023-09-27 17:59:45
是否有人成功地使三态复选框在TreeListView中正常工作,而不使用模型对象中的属性来存储检查状态?
因此,例如,会检查一个节点。应检查其所有子女(以及子女等),然后根据其兄弟姐妹CheckStates
检查其所有父母/祖父母。
我尝试了几种方法,但每种方法都在TreeListView类中得到一个ArgumentOutOfRange
/ArgumentException
。这包括以下内容:
- 将所有节点CheckStates存储在字典中,并用作
CheckStateGetter
事件的查找 - 当项
CheckState
更改时递归调用函数(并确保在程序更改CheckStates
时忽略后续的ItemCheck事件) - 调用一个函数来确定直接的子级/父级状态,并让TreeListView为每个受影响的节点激发
ItemChecked
事件
我经常从以下函数(在TreeListView.cs中)中得到错误:
- 获取第N项()
- GetChildren()-然后在GUI中展开/折叠屏蔽
- ProcessLButtonDown()
如果有人在这方面取得了成功,我会洗耳恭听。
我在TreeListView中也遇到了一些问题,并在GetChildren()函数中发现了一个问题。
GetChildren不必要地试图扩展相关分支以获取子级。这导致内部状态显示为展开,而视图保持折叠状态,并导致内部索引出现问题。
原始方法:
public virtual IEnumerable GetChildren(Object model) {
Branch br = this.TreeModel.GetBranch(model);
if (br == null || !br.CanExpand)
return new ArrayList();
if (!br.IsExpanded) // THIS IS THE PROBLEM
br.Expand();
return br.Children;
}
固定方法:
public virtual IEnumerable GetChildren(Object model) {
Branch br = this.TreeModel.GetBranch(model);
if (br == null || !br.CanExpand)
return new ArrayList();
br.FetchChildren();
return br.Children;
}
也许这至少解决了你的一些问题。
如果TreeListView自检("来自框")对您有好处,并且您只想知道所有员工在手动完成某些主复选框点击后的时间(这意味着:您单击,TreeListView(取消)检查所有儿童和家长),所以您需要在ObjectListView库中制作额外的事件(粗略地说):
''objectlistviewdemo''objectlistview''treelistview.cs
首先添加事件(我的事件很糟糕,但你知道该修复什么)
#region Events
public delegate void AfterTreeCheckEventHandler(object sender/*, object rowmodel*/);
/// <summary>
/// Triggered when clicked main checkbox checked and all related too.
/// </summary>
[Category("ObjectListView"),
Description("This event is triggered when clicked main checkbox checked and all related too.")]
public event AfterTreeCheckEventHandler AfterTreeCheckAndRecalculate;
#endregion
#region OnEvents
/// <summary>
/// Tell the world when a cell has finished being edited.
/// </summary>
protected virtual void OnAfterTreeCheckAndRecalculate(/*CellEditEventArgs e*/)
{
if (this.AfterTreeCheckAndRecalculate != null)
this.AfterTreeCheckAndRecalculate(this/*, e*/);
}
#endregion
其次,您需要修复"SetObjectCheckness"方法(1个递归方法用于1个简单+1个递归)
/// <summary>
/// Change the check state of the given object to be the given state.
/// </summary>
/// <remarks>
/// If the given model object isn't in the list, we still try to remember
/// its state, in case it is referenced in the future.</remarks>
/// <param name="modelObject"></param>
/// <param name="state"></param>
/// <returns>True if the checkedness of the model changed</returns>
protected override bool SetObjectCheckedness(object modelObject, CheckState state) {
// If the checkedness of the given model changes AND this tree has
// hierarchical checkboxes, then we need to update the checkedness of
// its children, and recalculate the checkedness of the parent (recursively)
bool result = SetObjectCheckednessHelper(modelObject, state, 0);
if (this.AfterTreeCheckAndRecalculate != null)
this.AfterTreeCheckAndRecalculate(this); //report that work is done
return result;
}
protected bool SetObjectCheckednessHelper(object modelObject, CheckState state, int i) //recursive
{
if (!base.SetObjectCheckedness(modelObject, state))
return false;
if (!this.HierarchicalCheckboxes)
return true;
// Give each child the same checkedness as the model
CheckState? checkedness = this.GetCheckState(modelObject);
if (!checkedness.HasValue || checkedness.Value == CheckState.Indeterminate)
return true;
foreach (object child in this.GetChildrenWithoutExpanding(modelObject))
{
this.SetObjectCheckednessHelper(child, checkedness.Value, i+1);
} //(un)check all children checkboxes
if (i == 0) //recalculate upper levels only in the case of first call
{
ArrayList args = new ArrayList();
args.Add(modelObject);
this.RecalculateHierarchicalCheckBoxGraph(args); //all upper checkboxes in intermediate state or (un)check
}
return true;
}
用法:
this.olvDataTree.AfterTreeCheckAndRecalculate += new BrightIdeasSoftware.TreeListView.AfterTreeCheckEventHandler(this.olvDataTree_TreeChecked);
private void olvDataTree_TreeChecked(object sender)
{
//some staff here
}