1

有没有人成功地让三态复选框在 TreeListView 中正常工作,而不使用模型对象中的属性来存储检查状态?

因此,例如,检查一个节点。应检查其所有孩子(和孩子的孩子等),然后应根据其兄弟姐妹检查其所有父母/祖父母CheckStates

我尝试了几种方法,但每种方法都在 TreeListView 类中获得ArgumentOutOfRange/ 。ArgumentException这包括以下内容:

  • 将所有节点 CheckStates 存储在 Dictionary 中并用作CheckStateGetter事件查找
  • 当项目更改时递归调用函数CheckState(并确保在以编程方式更改时忽略后续的 ItemCheck 事件CheckStates
  • 调用一个函数来确定直接的子/父状态,并让 TreeListViewItemChecked为每个受影响的节点触发事件。

我经常从以下函数中得到错误(在 TreeListView.cs 中):

  • GetNthItem()
  • GetChildren() - 然后在 GUI 中展开/折叠护罩
  • ProcessLButtonDown()

如果有人在这方面取得了成功,我会全力以赴。

4

2 回答 2

1

我对 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;
    }

也许这至少可以解决您的一些问题。

于 2013-02-15T14:14:36.263 回答
0

“当项目 CheckState 更改时递归调用函数(并确保在以编程方式更改 CheckState 时忽略后续 ItemCheck 事件)”

如果 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

其次,您需要修复“SetObjectCheckedness”方法(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
    }
于 2016-10-20T20:41:59.100 回答