标记的对象发生更改时,如何更新WinForms TreeView?

时间:2019-02-27 15:56:26

标签: c# winforms treeview

我有一个WinForms TreeView代表我的计算器数据。当我读入数据时,我将创建TreeView并用相应的对象标记每个TreeView节点。下面是一个示例TreeView。

SUM
    SUM
        TIMES
            UnitsSold
            UnitPrice
        IncomeFromContracts
    NEGATIVE SUM
        Rent
        Wages
        TIMES
            UnitsSold
            UnitMaterialCost

我从如下数据结构创建TreeView:

class Operand {
    bool IsNegated {get; set;}
}

class Operator : Operand {
    enum OperatorEnum { SUM, DIFFERENCE, TIMES }
    OperatorEnum MyEnum {get; set;}
    IList<Operand> Children {get; set;}
}

class VariableName : Operand {
    string Name {get; set;}
}

每个TreeNode都标记有相应的Operand。当选择TreeView中的项目时,带标签的项目将显示在面板中,以便您可以更改其属性。例如。当我选择一个项目时,会出现一个复选框,您可以在其中设置IsNegated值。我已经成功使用以下方法将该控件绑定到Operand对象:

negateCheckBox.DataBindings.Add("Checked", requirementTree.SelectedNode.Tag, "IsNegated");

单击复选框会适当地更新基础数据,但不会导致TreeView刷新其数据,因此,即使该项目的ToString()方法的返回值已更改(它现在带有“ NEGATIVE”前缀),因为TreeNode已经使用该字符串创建,所以不会更新。

我也有一些“添加”和“删除”按钮,它们在TreeView中创建其他节点并将其删除,但是所有这些都是手动操作的-更新基础数据结构,然后重建整个TreeView(这将导致视图刷新,这样我就可以验证我的其他绑定是否正常工作。

我需要采取什么步骤,以便不手动填充TreeView,而是将其完全绑定到我的数据结构,以便立即反映出这样的变化?似乎有很多方法可以绑定WinForms中的数据,但我不清楚哪种方法适用于哪种情况。

非常感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

基于Reza的评论,即TreeView不支持数据绑定,我提出了一个合理的解决方法。

每个“模型”类都实现INotifyPropertyChanged并在其任何属性更改时引发事件。

class Operand : INotifyPropertyChanged
{
    public bool IsNegated
    {
        get { return m_isNegated; }
        set { m_isNegated = value; RaisePropertyChanged(); }
    }
    private bool m_isNegated = false;

    private void RaisePropertyChanged([CallerMemberName]string prop = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
    }
}

然后我添加了一个虚拟控制器,该控制器将模型链接到TreeView节点:

public class OperandTreeNodeController

{
    private Requirement m_model;
    private TreeNode m_view;

    public OperandTreeNodeController(Requirement model, TreeNode view)
    {
        m_model = model;
        m_view = view;

        m_model.PropertyChanged += Model_PropertyChanged;
    }

    private void Model_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        m_view.Text = m_model.ToString();
    }
}

现在,每当我创建TreeNode时,我也会创建一个控制器。这里有一些内存“泄漏”,因为它们可以继续创建并附加到模型的PropertyChanged事件中,并且垃圾收集器可能永远不会清理它们,但是我已经在我的代码中通过添加Destroy()函数手动处理了并手动跟踪/销毁它们。

这似乎实现了我的大部分目标,所以除非有人有其他想法,否则我将坚持下去。