Autor |
Beitrag |
kostonstyle
      
Beiträge: 94
|
Verfasst: Mi 25.08.10 17:00
hallo miteinander
ich habe im Internet Sourcecode heruntergeladen, dort steht folgendes
C#-Quelltext 1: 2: 3: 4: 5:
| public class TreeViewItemViewModel : INotifyPropertyChanged { #region Data
static readonly TreeViewItemViewModel DummyChild = new TreeViewItemViewModel(); |
warum instanziert er hier Instanz von eigene Klasse? Was bewirkt man überhaupt damit?
Gruss kostonstyle
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Mi 25.08.10 18:15
Ein TreeView stellt einen Baum dar und ein Baum ist eine rekursive Datenstruktur: Jeder Knoten muss auf seine Unterknoten zugreifen können, die sinnigerweise von der gleichen Klasse sind. Also werden im Code auf jeden Fall Instanzen der eigenen Klasse vorkommen und auch instantiiert werden.
PS: Das Gesagte gilt für jede Baum-Struktur, aber speziell für deinen Code muss ich dich warnen: Wenn du noch nicht ganz fit in objektorientierter Programmierung bist, dürfte MVVM kaum zu bewältigen sein. Es ist äußerst elegant, aber von der Konzepten her äußerst heftig  .
_________________ >λ=
|
|
Yogu
      
Beiträge: 2598
Erhaltene Danke: 156
Ubuntu 13.04, Win 7
C# (VS 2013)
|
Verfasst: Mi 25.08.10 20:21
Kha hat folgendes geschrieben : | Ein TreeView stellt einen Baum dar und ein Baum ist eine rekursive Datenstruktur: Jeder Knoten muss auf seine Unterknoten zugreifen können, die sinnigerweise von der gleichen Klasse sind. Also werden im Code auf jeden Fall Instanzen der eigenen Klasse vorkommen und auch instantiiert werden. |
Das betrifft jetzt aber nicht den geposteten Quellcode, oder? Dort existiert nämlich ein statisches Feld, das eine Instanz der eigenen Klasse enthält, keine Liste mit Kindkonoten oder dem Elternknoten.
Dem Namen Dummy... nach zu schließen ist das entweder ein Test oder schlechter Programmierstil, auf jeden Fall vollkommen aus dem Zusammenhang gerissen. Sonst passiert hier genau dasselbe, was auch passieren würde, wenn eine andere Klasse TreeViewItemViewModel instanzieren würde.
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Mi 25.08.10 23:38
Naja, ich wollte erst einmal die Frage wortwörtlich beantworten, denn ohne weiteren Kontext lässt sich über das Feld wirklich wenig aussagen. Aber bei dem Namen des Feldes gehe ich doch mal davon aus  , dass es tatsächlich als Kindknoten hinzugefügt wird - höchstwahrscheinlich, um den Knoten ausklappbar zu machen und dann beim Ausklappen durch die eigentlichen, lazy nachgeladenen Daten ersetzt zu werden. Da der Dummy-Knoten keine Daten enthalten muss, kann er als Optimierung als Singleton verwaltet werden, aber der Hauptpunkt ist immer noch, dass wir es mit einer rekursiven Datenstruktur zu tun haben.
_________________ >λ=
|
|
kostonstyle 
      
Beiträge: 94
|
Verfasst: Mo 30.08.10 11:47
Hier ist gesamter Quellcode von Klasse TreeViewWithViewModelDemo
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158:
| using System; using System.Collections.ObjectModel; using System.ComponentModel;
namespace TreeViewWithViewModelDemo.LoadOnDemand { public class TreeViewItemViewModel : INotifyPropertyChanged { #region Data
static readonly TreeViewItemViewModel DummyChild = new TreeViewItemViewModel();
readonly ObservableCollection<TreeViewItemViewModel> _children; readonly TreeViewItemViewModel _parent;
bool _isExpanded; bool _isSelected;
#endregion // Data
#region Constructors
protected TreeViewItemViewModel(TreeViewItemViewModel parent, bool lazyLoadChildren) { _parent = parent;
_children = new ObservableCollection<TreeViewItemViewModel>();
if (lazyLoadChildren) _children.Add(DummyChild); }
private TreeViewItemViewModel() { }
#endregion // Constructors
#region Presentation Members
#region Children
public ObservableCollection<TreeViewItemViewModel> Children { get { return _children; } }
#endregion // Children
#region HasLoadedChildren
public bool HasDummyChild { get { return this.Children.Count == 1 && this.Children[0] == DummyChild; } }
#endregion // HasLoadedChildren
#region IsExpanded
public bool IsExpanded { get { return _isExpanded; } set { if (value != _isExpanded) { _isExpanded = value; this.OnPropertyChanged("IsExpanded"); }
if (_isExpanded && _parent != null) _parent.IsExpanded = true;
if (this.HasDummyChild) { this.Children.Remove(DummyChild); this.LoadChildren(); } } }
#endregion // IsExpanded
#region IsSelected
public bool IsSelected { get { return _isSelected; } set { if (value != _isSelected) { _isSelected = value; this.OnPropertyChanged("IsSelected"); } } }
#endregion // IsSelected
#region LoadChildren
protected virtual void LoadChildren() { }
#endregion // LoadChildren
#region Parent
public TreeViewItemViewModel Parent { get { return _parent; } }
#endregion // Parent
#endregion // Presentation Members
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName) { if (this.PropertyChanged != null) this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); }
#endregion // INotifyPropertyChanged Members } } |
Hier wird ein privater Konstruktor definiert,
C#-Quelltext 1: 2: 3: 4:
| private TreeViewItemViewModel() { } |
und ist dafür zuständig, dass DummyChild instanziert wird, warum?
|
|
Yogu
      
Beiträge: 2598
Erhaltene Danke: 156
Ubuntu 13.04, Win 7
C# (VS 2013)
|
Verfasst: Mo 30.08.10 12:05
kostonstyle hat folgendes geschrieben : | Hier wird ein privater Konstruktor definiert,
C#-Quelltext 37: 38: 39: 40:
| /* ... */ private TreeViewItemViewModel() { } |
und ist dafür zuständig, dass DummyChild instanziert wird, warum? |
Um das DummyChild zu erstellen, wird ein parameterloser Konstruktur benötigt:
kostonstyle hat folgendes geschrieben : | C#-Quelltext 15:
| /* ... */ static readonly TreeViewItemViewModel DummyChild = new TreeViewItemViewModel(); | |
Der öffentliche Konstruktor erwartet ja Parameter, die für das DummyChild nicht gedacht sind.
Kha hat folgendes geschrieben : | Aber bei dem Namen des Feldes gehe ich doch mal davon aus , dass es tatsächlich als Kindknoten hinzugefügt wird - höchstwahrscheinlich, um den Knoten ausklappbar zu machen und dann beim Ausklappen durch die eigentlichen, lazy nachgeladenen Daten ersetzt zu werden. Da der Dummy-Knoten keine Daten enthalten muss, kann er als Optimierung als Singleton verwaltet werden. |
Stimmt, in der vorliegenden Implementierung eines Baums schon. Ein Singleton wäre nicht möglich, wenn ein Knoten nur genau einen Parent-Knoten bekommen kann (wie System.Windows.Forms.TreeNode oder ein DOM-Knoten), weil der Dummy-Knoten ja auch zu mehreren Elternknoten zugewiesen werden können muss.
|
|
kostonstyle 
      
Beiträge: 94
|
Verfasst: Mo 30.08.10 13:50
erstmal vielen dank für answer...
also was ich noch nicht kapiere ist, warum der private constructor ausgeführt. Dazu habe ich ein Beispiel
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38:
| using System; using System.Collections.Generic; using System.Linq; using System.Text;
namespace Example { public class InstanceSelf { public static InstanceSelf ins = new InstanceSelf(); public static string vab1 = "Hallo"; public string vab2 = "Oh man";
public static string SetString { get; set; }
public static int SetInt { get; set; }
public int SetPInt { get; set; }
private InstanceSelf() { Console.WriteLine("I'm Instance"); }
} } |
So, wie man hier sieht, besitzt die Klasse InstanceSelf private constructor und es wird beim kompilieren ausgeführt. Dazu wird noch der Klassevariable "ins" instanziert. Warum ist der private Constructor
für die static Instanzierung oder für die Zuweisung von static Werte zuständig?
Das Main Programm sieht so aus
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25:
| using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using System.Collections;
namespace Example { class Program { static void Main(string[] args) { InstanceSelf.SetString = "Hello"; string outline = InstanceSelf.SetString; Console.WriteLine(outline);
InstanceSelf.vab1 = "Change Vab1"; InstanceSelf.ins.SetPInt = 600; Console.WriteLine(InstanceSelf.ins.SetPInt); Console.ReadLine(); } } } |
Mit "ins" kann ich dann auf alle public instanz Felder zugreifen.
Gruss kostonstyle
|
|
Yogu
      
Beiträge: 2598
Erhaltene Danke: 156
Ubuntu 13.04, Win 7
C# (VS 2013)
|
Verfasst: Mo 30.08.10 14:02
kostonstyle hat folgendes geschrieben : | Warum ist der private Constructor für die static Instanzierung oder für die Zuweisung von static Werte zuständig? |
Naja, der private Konstruktur ist nicht ausschließlich für die Erstellung statischer Member zuständig. Er wird eben in deinem Beispielcode und in dem aus dem ersten Posting verwendet. Stattdessen hätte man theoretisch auch irgendeinen anderen Konstruktor der Klasse verwenden können, zum Beispiel TreeViewItemViewModel(TreeViewItemViewModel parent, bool lazyLoadChildren). Dieser ist aber in der speziellen Situation nicht der richtige.
Der parameterlose Konstruktur ist nur deshalb privat, weil er nicht für anderen Klassen sichtbar sein soll. Die sollen die Klasse auf andere Wege instanzieren.
|
|
|