Autor Beitrag
kostonstyle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 94



BeitragVerfasst: Mi 25.08.10 17:00 
hallo miteinander
ich habe im Internet Sourcecode heruntergeladen, dort steht folgendes
ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2598
Erhaltene Danke: 156

Ubuntu 13.04, Win 7
C# (VS 2013)
BeitragVerfasst: Mi 25.08.10 20:21 
user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 94



BeitragVerfasst: Mo 30.08.10 11:47 
Hier ist gesamter Quellcode von Klasse TreeViewWithViewModelDemo
ausblenden volle Höhe 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:
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
{
    /// <summary>
    /// Base class for all ViewModel classes displayed by TreeViewItems.  
    /// This acts as an adapter between a raw data object and a TreeViewItem.
    /// </summary>
    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);
        }

        // This is used to create the DummyChild instance.
        private TreeViewItemViewModel()
        {
        }

        #endregion // Constructors

        #region Presentation Members

        #region Children

        /// <summary>
        /// Returns the logical child items of this object.
        /// </summary>
        public ObservableCollection<TreeViewItemViewModel> Children
        {
            get { return _children; }
        }

        #endregion // Children

        #region HasLoadedChildren

        /// <summary>
        /// Returns true if this object's Children have not yet been populated.
        /// </summary>
        public bool HasDummyChild
        {
            get { return this.Children.Count == 1 && this.Children[0] == DummyChild; }
        }

        #endregion // HasLoadedChildren

        #region IsExpanded

        /// <summary>
        /// Gets/sets whether the TreeViewItem 
        /// associated with this object is expanded.
        /// </summary>
        public bool IsExpanded
        {
            get { return _isExpanded; }
            set
            {
                if (value != _isExpanded)
                {
                    _isExpanded = value;
                    this.OnPropertyChanged("IsExpanded");
                }

                // Expand all the way up to the root.
                if (_isExpanded && _parent != null)
                    _parent.IsExpanded = true;

                // Lazy load the child items, if necessary.
                if (this.HasDummyChild)
                {
                    this.Children.Remove(DummyChild);
                    this.LoadChildren();
                }
            }
        }

        #endregion // IsExpanded

        #region IsSelected

        /// <summary>
        /// Gets/sets whether the TreeViewItem 
        /// associated with this object is selected.
        /// </summary>
        public bool IsSelected
        {
            get { return _isSelected; }
            set
            {
                if (value != _isSelected)
                {
                    _isSelected = value;
                    this.OnPropertyChanged("IsSelected");
                }
            }
        }

        #endregion // IsSelected

        #region LoadChildren

        /// <summary>
        /// Invoked when the child items need to be loaded on demand.
        /// Subclasses can override this to populate the Children collection.
        /// </summary>
        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(thisnew PropertyChangedEventArgs(propertyName));
        }

        #endregion // INotifyPropertyChanged Members
    }
}


Hier wird ein privater Konstruktor definiert,
ausblenden C#-Quelltext
1:
2:
3:
4:
        // This is used to create the DummyChild instance.
        private TreeViewItemViewModel()
        {
        }

und ist dafür zuständig, dass DummyChild instanziert wird, warum?
Yogu
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2598
Erhaltene Danke: 156

Ubuntu 13.04, Win 7
C# (VS 2013)
BeitragVerfasst: Mo 30.08.10 12:05 
user profile iconkostonstyle hat folgendes geschrieben Zum zitierten Posting springen:
Hier wird ein privater Konstruktor definiert,
ausblenden C#-Quelltext
 
37:
38:
39:
40:
/* ... */
        // This is used to create the DummyChild instance.
        private TreeViewItemViewModel()
        {
        }

und ist dafür zuständig, dass DummyChild instanziert wird, warum?

Um das DummyChild zu erstellen, wird ein parameterloser Konstruktur benötigt:

user profile iconkostonstyle hat folgendes geschrieben Zum zitierten Posting springen:
ausblenden C#-Quelltext
 
15:
/* ... */
static readonly TreeViewItemViewModel DummyChild = new TreeViewItemViewModel();

Der öffentliche Konstruktor erwartet ja Parameter, die für das DummyChild nicht gedacht sind.

user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 94



BeitragVerfasst: 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
ausblenden volle Höhe 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:
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
ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2598
Erhaltene Danke: 156

Ubuntu 13.04, Win 7
C# (VS 2013)
BeitragVerfasst: Mo 30.08.10 14:02 
user profile iconkostonstyle hat folgendes geschrieben Zum zitierten Posting springen:
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.