TreeView填充/绑定

时间:2016-10-21 19:37:46

标签: winforms dynamic data-binding treeview

我创建了一个解析器来读取按以下方式格式化的文件:

version="v4.5.32"
name="Test File"
date="2513.04.02"
players=
{
    {
        first_name="John"
        last_name="Smith"
        country=12
        id=0
    }
    {
        first_name="Mario"
        last_name="Rossi"
        country=56
        id=1
    }
}
next_player_id=2
matches=
{
    22 47 88 1045 1048 3511
}
settings=
{
    match_prefix="game"
    match_reward_scalar=1,55
    match_sets_points=
    {
        0,5 0,75 1,0
    }
    next_event_id=56
    next_event_fired=false
    next_event_probability=0,33
}
...

基本上,这些文件包含一个键/值对列表,其中键始终是一个字符串,值可以是简单值(布尔值,日期,浮点数,整数,字符串),记录(键的子列表/值对(如settings)或数组(由matches之类的简单值或players之类的记录组成)。为了解析和处理这些值,我创建了3个简单的类。

1)MyPair

public sealed class MyPair
{
    public MyKey Key { get; }
    public MyValue Value { get; }

    public MyPair(MyKey key, MyValue value) { ... }

    public override String ToString()
    {
        return String.Concat(Key, " = ", Value);
    }
}

2)MyKey

public sealed class MyKey
{
    public String Name { get; }
    ... // other properties set by checking the name in the constructor

    public Key(String name) { ... }

    public override String ToString()
    {
        return Name;
    }
}

3)MyValue

public sealed class MyValue
{
    private readonly dynamic m_UnderlyingValue;
    private readonly MyValueCategory m_Category;

    public dynamic UnderlyingValue
    {
        get { return m_UnderlyingValue; }
    }

    public Boolean Container
    {
        get { return ((m_Category == ValueCategory.Array) || (m_Category == ValueCategory.Record)); }
    }

    public MyValueCategory Category
    {
        get { return m_Category; }
    }

    public MyValue(DateTime underlyingValue)
    {
        if (underlyingValue == null)
            throw new ArgumentNullException("underlyingValue");

        m_UnderlyingValue = underlyingValue;
        m_Category = MyValueCategory.DateTime;
    }

    public MyValue(Boolean underlyingValue) { ... }

    public MyValue(Double underlyingValue) { ... }

    public MyValue(Int64 underlyingValue) { ... }

    public MyValue(MyPair[] underlyingValue) { ... }

    public MyValue(MyValue[] underlyingValue) { ... }

    public MyValue(String underlyingValue) { ... }

    public override String ToString()
    {
        switch (m_Category)
        {
            case MyValueCategory.Array:
                return String.Concat("Array[", m_UnderlyingValue.Length, "]");

            case MyValueCategory.Boolean:
                return String.Concat("Boolean[", (m_UnderlyingValue ? "true" : "false"), "]");

            case MyValueCategory.DateTime:
                return String.Concat("DateTime[", m_UnderlyingValue.ToString("yyyy.MM.dd", CultureInfo.InvariantCulture), "]");

            case MyValueCategory.Float:
                return String.Concat("Float[", m_UnderlyingValue.ToString("F3", CultureInfo.InvariantCulture), "]");

            case MyValueCategory.Integer:
                return String.Concat("Integer[", m_UnderlyingValue.ToString("F0", CultureInfo.InvariantCulture), "]");

            case MyValueCategory.Record:
                return String.Concat("Record[", m_UnderlyingValue.Length, "]");

            default:
                return String.Concat("Text[", m_UnderlyingValue, "]");
        }
    }
}

public enum MyValueCategory
{
    Array,
    Boolean,
    DateTime,
    Float,
    Integer,
    Record,
    Text
}

解析过程就像一个魅力,并返回一个MyValue实例,它就像我解析的所有内容一样,就像容器/根节点一样。

我没有使用WPF表单,只是简单Winforms。我想用解析后的数据分层填充TreeView控件,然后使这些数据响应对TreeView节点所做的更改。我真的无法弄清楚如何将数据绑定到控件本身并允许镜像操作。

有什么建议吗?

1 个答案:

答案 0 :(得分:3)

您可以使用以下代码递归填充TreeView

protected override void OnLoad( EventArgs e )
{
    base.OnLoad( e );

    MyValue root = new MyParser().Parse( "MyFilename.own" );
    Populate( treeView1.Nodes, root.UnderlyingValue );
}

protected void Populate( TreeNodeCollection nodes, IList list )
{
    if( list is MyPair[] )
    {
        foreach( MyPair pair in list )
        {
            TreeNode node = new TreeNode();
            node.Text = pair.ToString();
            node.Tag = pair;
            nodes.Add( node );

            if( pair.Value.Container )
                Populate( node.Nodes, (IList)pair.Value.UnderlyingValue );
        }
    }

    if( list is MyValue[] )
    {
        foreach( MyValue value in list )
        {
            TreeNode node = new TreeNode();
            node.Text = value.ToString();
            node.Tag = value;
            nodes.Add( node );

            if( value.Container )
                Populate( node.Nodes, (IList)value.UnderlyingValue );
        }
    }
}

结果看起来像那样:

Populated TreeView

正如@Reza Aghaei已经提到过,通过数据绑定无法做到这一点。添加/删除节点后,您必须手动维护列表。将node.Tag设置为相应的对或值可以让您轻松找到并修改它们。