2016-10-21 6 views
2

habe ich einen Parser, der Dateien in der folgenden Weise formatiert lautet:TreeView Bestücken von/Binding

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 
} 
... 

Grundsätzlich diese Dateien enthalten eine Liste von Schlüssel/Wert-Paare, in denen Schlüssel sind immer ein String und Werte können sein entweder ein einfacher Wert (boolean, Datum, float, integer, string), einen Datensatz (eine Unterliste von Schlüssel/Wert-Paare wie settings) oder ein Array (zusammengesetzt durch einfache Werte wie matches oder Datensätze wie players). Um diese Werte zu analysieren und zu behandeln, habe ich 3 einfache Klassen erstellt.

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 
} 

Der Parsing-Prozess funktioniert wie ein Charme und gibt mir eine MyValue Instanz, wie funktioniert Ein Container/Root-Knoten für alles, was ich geparst habe.

verwende ich nicht WPF Formen, einfach nur Winforms. Ich möchte ein TreeView Steuerelement hierarchisch mit den geparsten Daten füllen und dann diese Daten als Reaktion auf die Änderungen an den TreeView Knoten vornehmen. Ich kann wirklich nicht herausfinden, wie man Daten an das Steuerelement selbst bindet und eine gespiegelte Manipulation erlaubt.

Irgendwelche Vorschläge bitte?

+0

** (1) ** "TreeView" unterstützt keine Datenbindung und Sie sollten Knoten manuell zum TreeView-Steuerelement hinzufügen. ** (2) ** Wenn Sie die Eingabe in einer organisierten und regulären Struktur wie einem 'XML' oder' JSON' oder etwas wie 'XElement' analysieren können, dann können Sie es einfach mit einer rekursiven Methode wie' TreeView' laden Dieses 'void Populate (TreeNode Knoten, Elemente [] Elemente)'. ** (3) ** Momentan scheint die Eingabe nicht regulär zu sein, zum Beispiel 'match_reward_scalar = 1,55' und' match_sets_points = {0,5 0,75 1,0} 'sind Array, aber die erste nicht habe {} während der zweite hat. –

+0

Ist es für Sie akzeptabel, wenn jemand eine Antwort postet, die eine reguläre Struktur wie XML/JSON oder etwas anderes verwendet? Es ist nicht einfach, deinen Klassen zu folgen und der Eingabetext scheint nicht regelmäßig zu sein. Wenn dies nicht akzeptabel ist, sollten Sie ein [minimales, vollständiges und verifizierbares Beispiel] veröffentlichen (http://stackoverflow.com/help/mcve). –

Antwort

3

Sie können Ihre TreeView rekursiv mit diesem Code füllen:

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); 
     } 
    } 
} 

Ergebnis sieht dann wie folgt aus:

Populated TreeView

Wie @Reza Aghaei bereits erwähnt es nicht möglich ist, dies zu tun, über Datenbindung. Sie müssen Ihre Listen nach dem Hinzufügen/Entfernen eines Knotens manuell pflegen. Wenn Sie node.Tag auf das entsprechende Paar oder den entsprechenden Wert setzen, können Sie sie leicht finden und ändern.