"Recursively calling a function when an items CheckState changes (and ensuring the subsequent ItemCheck events are ignored while programatically changing CheckStates)"
In case TreeListView self-checking ("from box") is good for you and you just want to know when all staff after your manual some main checkbox clicking is done
(this mean: you click, TreeListView (un)check all childrens and parents),
so you need to make extra event in ObjectListView Library (in rough way):
\objectlistviewdemo\objectlistview\treelistview.cs
Firstly add event (my events are bad but you know what to fix)
#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
Secondly you need to fix "SetObjectCheckedness" method (1 recursive method for 1 simple + 1 recursive)
/// <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;
}
usage:
this.olvDataTree.AfterTreeCheckAndRecalculate += new BrightIdeasSoftware.TreeListView.AfterTreeCheckEventHandler(this.olvDataTree_TreeChecked);
private void olvDataTree_TreeChecked(object sender)
{
//some staff here
}