Laden...

DependencyProperty - generelle Fragen zum Sinn :)

Erstellt von Beathoven vor 12 Jahren Letzter Beitrag vor 12 Jahren 7.052 Views
B
Beathoven Themenstarter:in
23 Beiträge seit 2011
vor 12 Jahren
DependencyProperty - generelle Fragen zum Sinn :)

Hallo zusammen,

ich versuche mir gerade aus drei verschiedenen Quellen ein grundsätzliches Verständnis für DependencyProperties anzueignen.
Ich habe in etwa verstanden, wie das System funktioniert:
anstatt eine Eigenschaft wie üblich direkt anzusprechen, sorgen GET und SET dafür, dass mit GetValue und SetValue (aus DependencyObject) der entsprechende Wert geholt/gesetzt wird.
Dabei erstellt die PropertyEngine von WPF eine Art Key/Value Paar, dass sie irgendwo ablegt.
Soweit - sogut.
Mein Problem daran ist, dass ich noch nicht verstanden habe, warum man das überhaupt macht. Ich sehe noch keinen Vorteil.

Ein Beispiel:
ich erstelle eine Klasse "TextDreher", diese erbt von FrameworkElement ( und damit auch von DependencyObject).
TextDreher erhält nun eine einfache Property von typ double: "drehRadius".

Würde ich nun eine Subklasse von Textdreher erstellen, komme ich ja dennoch problemlos an den Wert von drehRadius.

Warum sollte ich das also umständlich als DependencyProperty implementieren? Was hab ich übersehen?

Danke und LG
Beathoven

1.552 Beiträge seit 2010
vor 12 Jahren

Hallo Beathoven,

einfach gesagt: Ohne DependencyProperties kannst du dem Benutzer deines CustomControl kein Binding an den Eigenschaften anbieten.

Gruß
Michael

Mein Blog
Meine WPF-Druckbibliothek: auf Wordpress, myCSharp

5.658 Beiträge seit 2006
vor 12 Jahren

Hi Beathoven,

es geht um Abhängigkeiten, wie der Name schon sagt. Ist ein Objekt vom anderen abhängig, muß es irgendwie darüber informiert werden, wenn sich das andere Objekt (bzw. deren Properties) ändert. Das ist in erster Linie wichtig, um das UserInterface automatisch aktualisieren zu könnne, wenn Daten geändert werden. Im Prinzip ließe sich das noch mit dem INotifyPropertyChanged-Interface implementieren, aber die DependencyProperties haben das alles schon fertig implementiert und haben auch Lösungen für Readonly-Properties, Vererbung und gegenseitige Abhängigkeiten.

Spätestens wenn man mit WPF Benutzeroberflächen erstellt, kommt man um die Benutzung nicht herum, da alle Controls darauf basieren. Dann versteht man auch sehr schnell den Sinn hinter dem Konzept, und warum das in Verbindung mit DataBinding einem ermöglicht, sehr schnell gut funktionierende Benutzeroberflächen zu schreiben.

Christian

Weeks of programming can save you hours of planning

B
Beathoven Themenstarter:in
23 Beiträge seit 2011
vor 12 Jahren

Hey, danke für die schnellen Antworten.
Natürlich ist mir immer noch nicht ganz klar, warum, weshalb und wieso - aber ich habe eine Ahnung.

Demzufolge greife ich Christians Antwort noch mal auf und stelle weitere Fragen 😃

Seh ich das richtig: eine Property als DependencyProperty zu definieren macht genau dann nur Sinn, wenn ich weiß, dass von meiner Klasse geerbt werden könnte - und eine Änderung an den Werten der Propertys dann in den Subklassen behandelt werden muss?

Woher weiß die Subklasse denn dann, dass sich was geändert hat?
Gerade diese Frage verwirrt mich etwas, denn bisher habe ich noch keinen Weg gefunden. Mir ist bekannt, dass es eine Klasse "PropertyChangedCallback" existiert. Der Konstruktor dieser Klasse erwartet einen Methodennamen, der dann entsprechend die Änderungen auswerten kann.
Aber: diese Klasse "setze" ich ja gar nicht in einer Subklasse, oder doch? Und wenn ja - wie?

Es ist schwierig für mich zu erklären, wo genau das Problem liegt, da alle Beispiele die ich im Netz so finde, einfach nicht vergleichbar sind.
Ich arbeite mich aber aktuell durch http://www.trivadis.com/fileadmin/user_upload/PDFs/Trivadis_in_der_Presse/070605_DotNet_Gewuenschte_Abhaengigkeit.pdf

Vielleicht kennt ja jemand dieses Dokument und kann meinen Gedanken so besser folgen 😃

Danke und LG
Beathoven

S
753 Beiträge seit 2006
vor 12 Jahren

Guck dir mal das hier an: http://wpftutorial.net/DependencyProperties.html
Vielleicht hilft es

Life is a short

5.742 Beiträge seit 2007
vor 12 Jahren

eine Property als DependencyProperty zu definieren macht genau dann nur Sinn, wenn ich weiß, dass von meiner Klasse geerbt werden könnte - und eine Änderung an den Werten der Propertys dann in den Subklassen behandelt werden muss?

Nein, dafür ruft man im Setter einer herkömmlichen Property einfach eine virtuelle Methode auf, die dann überschreieben werden kann bzw. feuert ein Event.

Die MSDN fasst IMHO ganz gut zusammen, wofür man eine Dependency Property braucht:

Represents a property that can be set through methods such as, styling, data binding, animation, and inheritance.

Eine Dependency Property bietet also Unterstützung für Animationen und Styles - somit hat sie u.U. mehrere Werte "gleichzeitig":
Ohne DependencyProperty könntest du Styles nicht dynamisch ändern, Animationen nicht beenden, usw.

Generell gilt aber:
Dependency Properties nur zu DependencyObjects hinzufügen - und nur von DependencyObject erben, wenn die Klasse später Teil des visuellen oder logischen Baums der WPF sein soll (also im Prinzip nur bei Controls).

5.658 Beiträge seit 2006
vor 12 Jahren

Hi Beathoven ,

Seh ich das richtig: eine Property als DependencyProperty zu definieren macht genau dann nur Sinn, wenn...

Um es kurz zu machen: Definieren mußt du ein DependencyProperty nur, wenn du WPF-Controls erstellst. Aber benutzen tust du es immer dann, wenn du in XAML Databinding oder Styles anwendest.

Christian

Weeks of programming can save you hours of planning

B
Beathoven Themenstarter:in
23 Beiträge seit 2011
vor 12 Jahren

Ich komme immer näher 😃

Also frag ich munter weiter:
Ich habe mir mal die Klasse "Stackpanel" angeschaut, dort wird eine DependencyProperty definiert: OrientationProperty.

Jetzt ist das Ding aber statisch und das finde ich unlogisch.
Ausgehend von einer ganz einfachen Property würde "static" bedeuten, dass der beinhaltende Wert sich auf allen Instanzen des Objekts ändern würde, auch wenn ich es nur an einer Stelle ändere.

Jetzt das Unlogische: Ich kann ja unendlich viele Stackpanel in mein Fenster einbauen - aber nur weil ich ein Panel auf "horizontal" gesetzt habe, heisst das noch lange nicht, dass alle anderen mitziehen (wäre auch doof).

Aber wie kommt das?
Ja ich weiß - da gibts eine Default-Einstellung - aber static ist static, oder nicht?

LG und danke 😃

6.862 Beiträge seit 2003
vor 12 Jahren

Static ist static, da hast du recht, aber statische DependencyProperties gibt es nicht. Das was du da hast, ist nur der Identifier des DependencyProperties. Mit diesem kannst du auf das eigentliche Dependency Property zugreifen mit GetValue und SetValue. Das wird in deinem verlinkten Artikel genauso erklärt.

Baka wa shinanakya naoranai.

Mein XING Profil.

B
Beathoven Themenstarter:in
23 Beiträge seit 2011
vor 12 Jahren

Stimmt schon - das steht im Artikel, aaaber:

mit "...= DependencyProperty.Register(....)" kann man eine DependecyProperty registrieren. Dazu gibt man als erstes den Namen der Eigenschaft als String an.
Angenommen ich schreibe da "xyz" rein, dann muss die Engine ja ein Key/Value Paar erstellen, das in etwa so aussieht:

Key: StackPanel.OrientationProperty.xyz
Value: Vertical

Es gibt also nur einen Identifier - oder seh ich das falsch ? (Mit Sicherheit seh ich das falsch, aber wo ist der Denkfehler 😃 ? )

Danke und LG
Beathvoen

5.658 Beiträge seit 2006
vor 12 Jahren

Ich schätze mal, das "unlogische" dabei ist, daß der Framework eine NamingConvention voraussetzt. Man braucht ein statisches DependencyProperty und das nicht-statische (eigentliche) Property. Für das DependenyProperty gelten die Regeln, daß es als static und public deklariert sein muß, und immer so heißen muß wie das entsprechende Property + "Property".

Also in deinem Fall heißt das DependencyProperty für StackPanel.**Orientation **"OrientationProperty". Obwohl das public ist, interessiert es dich eigentlich nicht, du verwendest immer StackPanel.Orientation.

Christian

Weeks of programming can save you hours of planning

1.552 Beiträge seit 2010
vor 12 Jahren

Und was noch wichtig ist:
Es soll keine Logik in den Properties vorhanden sein. Denn die Properties werden nie aufgerufen. Es sei denn druch deinen Code. Wenn du Logik in den Properties setzt und dort drinnen validierst, kann diese Property auch über Code durch SetValue(...,...) gesetzt werden und somit die Property Validation umgangen werden. Dazu gibt es beim Register der DependencyProperty die entsprechenden Überladungen.

Mein Blog
Meine WPF-Druckbibliothek: auf Wordpress, myCSharp

B
Beathoven Themenstarter:in
23 Beiträge seit 2011
vor 12 Jahren

Ja l*** mich am A**** - ich glaub ich habs kapiert 😄

Zur Sicherheit bitte ich Euch: korrigiert mich wenn ich falsch liege:

  1. Dependency Properties machen nicht für jede Property Sinn.
  2. Dependency Properties verwende ich nur in WPF-Controls.
  3. Die Namenkonvention befiehlt, dass eine DP immer statisch sein und public deklariert werden muss.
  4. Nur weil es statisch ist, heisst es nicht, dass es in diesem Fall genau so zu verstehen ist. Die Property Engine nutzt diese statische Variable als TEIL des Schlüssels, um die DP zuordnen zu können.
  5. Die PropertyEngine checkt, dass ich z.B. 50 StackPanels habe, die aber die selbe statische DP zeigen. Dabei checkt die PE aber auch, dass jede DP einzeln zu behandeln ist.
  6. Bei der Suche nach dem Wert der DP, prüft die PE die folgende Liste (angefangen bei 10) und nimmt den Wert, der zuletzt(!) gesetzt wurde. (guckst Du hier:Klick )

Lieg ich soweit richtig ?

Danke und Gruß
Beathoven

6.862 Beiträge seit 2003
vor 12 Jahren

Hallo,

Nicht ganz, aber ich fürchte da haben auch die letzten Ergänzungen im Thread dazu beigetragen.

Zu 2. Nein, DependencyProperties verwendet man bei jedem DependencyObject, nicht nur Controls. DependencyObject ist ja ne wichtige Basisklasse in WPF und Klassen wie Styles, Animations etc. sind keine Controls, könnten ohne DependencyProperties aber nicht funktionieren.

Zu 3. Nein, DependencyProperties sind nicht statisch (wie schon oben geschrieben). Statisch ist nur der Identifier mithilfe dessen man auf die DependencyProperties per GetValue und SetValue zugreifen kann. Der muss auch nicht public sein, protected geht genauso, nur bei private schränkt sich die Nützlichkeit dann schon bissle ein.
Damit erledigt sich auch 4, weil DPs nicht statisch sind.

Zu 5. Abgesehen von der Aussage statisches DP, stimmt es prinzipiell. Bei GetValue wird zwar nur der DP Identifier übergeben, aber die Property Engine hat noch das entsprechende Objekt als Schlüssel um zwischen verschiedenen Instanzen einer Klasse unterscheiden zu können. Wobei das aber ein Interna ist, welches für die Praxis vollkommen egal ist.

Zu 6. Stimmt nicht ganz, nicht der Wert der zuletzt gesetzt wird zählt, sondern der Wert mit der höchsten Priorität. Und das Bild zeigt nur, wie der Basiswert bestimmt wird. Das muss nicht der Wert sein, den das Property bei GetValue liefert. Der Basiswert wird nur als Grundlage benutzt. Animationen, Value Coercion etc. können den effektiven Wert den GetValue liefert, noch ändern.

Es soll keine Logik in den Properties vorhanden sein. Denn die Properties werden nie aufgerufen.

So wie sie dasteht, verwirrt die Aussage ziemlich imo. Was du meinst sind die Property Wrapper eines Dependency Properties und nicht aufgerufen stimmt auch nur für den XAML Parser. In der Praxis heißt das, dass bei Elementen welche in XAML verwendet werden, direkt auf das DP zugegriffen wird, statt über den Property Wrapper. Daher ist die Aussage das keine Logik in den Wrappern enthalten sein darf richtig. Aber das gilt wie gesagt nur für diesen Fall, nicht so allgemein wie die Ursprungsaussage war. Weil dann müsste man sich echt fragen wozu die Wrapper da sind 😉

Baka wa shinanakya naoranai.

Mein XING Profil.