2010-12-21 8 views
7

Ich mochte nicht wie verbose dp's sind, da der meiste Code nur wiederholt wird, ich habe es nur in eine generische Klasse gewickelt.Warum wickeln Leute DependencyProperties nicht in einer generischen Klasse ein?

Nachdem ich ziemlich viel Beispielcode gesehen habe, habe ich mich gefragt, warum mehr Leute nicht dasselbe machen.

Ich habe keine Probleme in meiner Demo-Anwendung zu sprechen, und es macht die ViewModels einfacher zu verwalten.

Probe:

class GenericDependancyProperty<T> : DependencyObject 
{ 
    // Value dependency property 
    public static readonly DependencyProperty ValueProperty = 
     DependencyProperty.Register("Value", typeof(T), typeof(GenericDependancyProperty), 
      new FrameworkPropertyMetadata((T)default(T), 
       new PropertyChangedCallback(OnValueChanged))); 

    // getter/setter for the Value dependancy property 
    public T Value 
    { 
     get { return (T)GetValue(ValueProperty); } 
     set { SetValue(ValueProperty, value); } 
    } 

    // Handles changes to the Value property.  
    private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     GenericDependancyProperty<T> target = (GenericDependancyProperty<T>)d; 
     T oldValue = (T)e.OldValue; 
     T newValue = target.Value; 
     target.OnValueChanged(oldValue, newValue); 
    } 

    // Provides derived classes an opportunity to handle changes to the Value property. 
    protected virtual void OnValueChanged(T oldValue, T newValue) 
    { 
     if (ValueChanged != null) 
     { 
      ValueChanged(newValue); 
     } 
    } 

    // Value changed event 
    public event Action<T> ValueChanged; 
} 

Ist dies eine schlechte Idee?

Antwort

13

Es ist keine schlechte Idee und einen Versuch wert, aber es wird nicht funktionieren!

Sie haben im Wesentlichen eine einzelne Abhängigkeitseigenschaft mit dem Namen "Value" definiert, dies ist OK, wenn Sie nur über Ihren CLR-Wrapper (dh den get/set-Code für Ihre Value-Eigenschaft) darauf zugreifen Das Framework beeinflusst die Abhängigkeitseigenschaft direkt. Zum Beispiel können Stil-Setter und Animationen Ihre Abhängigkeitseigenschaft nicht verwenden.

ich Ihnen zu teilen Schmerz mit dem DP-Kesselblech Code, weshalb ich mit einer deklarativen Lösung kam:

[DependencyPropertyDecl("Maximum", typeof(double), 0.0)] 
[DependencyPropertyDecl("Minimum", typeof(double), 0.0)] 
public partial class RangeControl : UserControl 
{ 
    ... 
} 

Die durch eine T4-Vorlage tatsächliche Abhängigkeitseigenschaften erzeugen in Visual Studio.

http://www.scottlogic.co.uk/blog/colin/2009/08/declarative-dependency-property-definition-with-t4-dte/

Colin E.

+0

Hey, ich habe Ihren Code vor einiger Zeit komplett ausgepackt und konvertiert, um alle benutzerdefinierten Typenbeschreibungen zu erstellen. Es öffnete meine Augen wirklich für das Potential von T4. – Will

+0

Danke Will - Ich bin froh, dass es dir gefallen hat. Ich bin jetzt süchtig nach T4 ;-) – ColinE

0

Da Ihr ValueProperty statisch ist, wird der Wert nicht ändern, egal, wie Sie Ihre Klasse instanziiert. Ich sehe nicht, wie das funktionieren würde.

+0

Abhängigkeitseigenschaften werden immer als statisch definiert. – ColinE

+0

Ja, aber jede Instanz von GenericDependancyProperty teilt in diesem Fall dieselbe "ValueProperty". – weilin8

1

Ich denke, die Hauptsache ist, dass Sie dies tun, um Ihre Ansicht-Modell-Klassen sauberer zu halten, aber es gibt keinen Grund, Abhängigkeitseigenschaften in View-Modellen zu verwenden.

Wie Colins Antwort zeigt, ist es am üblichsten, Abhängigkeitseigenschaften in abgeleiteten/Benutzersteuerelementen zu deklarieren. Das Ansichtsmodell enthält normalerweise Standardeigenschaften und implementiert INotifyPropertyChanged.

Darüber hinaus ist es sinnvoll, Abhängigkeitseigenschaften in die abgeleitete Steuerelementklasse selbst anstatt in eine separate generische/statische Klasse einzufügen, da Sie sie statisch referenzieren müssen: MySlider.SpecialOpacityProperty. Wenn Sie diese Dinge in einer einzigen Klasse haben, könnten Sie nicht zwei Eigenschaften mit demselben Namen (für verschiedene Steuerelemente) haben, oder wenn Sie eine generische Klasse verwenden, können Sie sie nicht in XAML referenzieren.

+0

Einige gute Punkte ... hatten das nicht bemerkt. DPs sind nicht wirklich für ViewModels geeignet. – ColinE

+0

Hängt davon ab, DPs sind viel schneller als INotificationPropertyChanged, wie ich mich erinnere. Nicht, dass ich DPs in ViewModels selbst stelle ... – Stefan

+0

Sie sind schneller, aber es führt Sie dann dazu, UI-DLLs wie WindowsBase.dll zu referenzieren. – kevindaub

0

Ihre Lösung ist nicht durchführbar, flexibel und überhaupt nicht skalierbar.

Da C# nur eine einzige Basisklasse zulässt, kann jede Klasse bei Ihrem Ansatz gleichzeitig eine DP haben.

Deshalb wird es nicht funktionieren.

Was Sie tun sollten, um Ihre Schmerzen zu lindern, verwenden Sie snippets oder code generation als Colin erwähnt.

Und denken Sie daran, wir alle teilen den gleichen Schmerz.

Verwandte Themen