2010-09-04 12 views
11

Oder „, wie Sie sicherstellen, dass alle Ihre Bindungen korrekt bleiben?
(dies irgendwie lang ist, aber Geduld mit mir, ich versuchte, es so kurz zu machen, wie ich kann)Statische Überprüfung der Bindungen

Betrachten sie das folgende Beispiel:

<TextBox Name="tb" /> 
    <TextBlock Text="{Binding Text.TheProp, ElementName=tb}" /> 

es ist perfekt zum Zeitpunkt der Kompilierung bekannt, dass die Bindung nicht korrekt ist (dh der Parser die Art des Elements kennt tb, und deshalb weiß es die Art der esistEigenschaft, und daher weiß es, dass TheProp nicht existiert).
Noch wird dieser Code kompilieren und ausführen (obwohl mit einer verbindlichen Fehlermeldung in der Debug-Ausgabe).

Dieses Verhalten kann in einigen Situationen sehr nützlich sein: Egal, welcher genaue Typ meine Daten sind, solange es geeignete Eigenschaften hat, bin ich in Ordnung. So erhalten wir eine Art "deklaratives Entenschreiben".

Aber, Ente tippen ist nicht immer eine gute Sache.
Während ich das MVVM-Muster verwende, kenne ich (meistens) die genauen Typen aller meiner ViewModel-Objekte. Auf der anderen Seite werden die Modelle im Laufe der Zeit immer komplexer, was mich über zukünftige Umgestaltungen beunruhigt: Was passiert, wenn ich beschließe, einige Eigenschaften umzubenennen oder, Gott bewahre, sie in ein separates aggregiertes Objekt zu legen? Was wird mit all meinen Bindungen dann passieren? Muss ich alle XAML-Dateien von Hand rechen lassen? Und auch ohne Refactoring - was ist, wenn ich einfach einen Tippfehler mache?

Ein ähnliches Problem ist bereits an anderen Stellen von XAML gelöst. Wenn Sie beispielsweise einen falschen Eigenschaftsnamen in Style/Setter/@Property eingeben, erhalten Sie einen Kompilierzeitfehler.
TemplateBinding bietet auch eine solche Überprüfung. Was sehr praktisch ist.

Also, im Idealfall, ich würde gerne so etwas sehen:

ProductViewModel.cs:

public class ProductViewModel 
    { 
     public Name { get; set; } 
     public Price { get; set; } 
    } 

ProductView.XAML:

<UserControl x:Class="Shopping.View.ProductView" 
       x:DataContextType="vm:ProductViewModel" 
       xmlns:vm="clr-namespace:Shopping.ViewModel" 
       ... > 
     <TextBox Text="{Binding Name}" /> <!-- OK --> 
     <TextBox Text="{Binding Price}" /> <!-- OK --> 
     <TextBox Text="{Binding ABC}" /> <!-- Compile time error: there is no property ABC in ProductViewModel --> 
    </UserControl> 

ShoppingCart. XAML:

<UserControl x:Class="Shopping.View.ShoppingCartView" 
       x:DataContextType="vm:ShoppingCartViewModel" 
       xmlns:vm="clr-namespace:Shopping.ViewModel" 
       ... > 
     <ItemsControl ItemsSource="{Binding Products}" 
         ItemType="vm:ProductViewModel" > <!-- Static check happens here 
                  ShoppingCartViewModel.Products must 
                  implement IEnumerable<ProductViewModel> --> 
      <ItemsControl.ItemTemplate> 
       <DataTemplate DataType="vm:ProductViewModel"> 
        <view:ProductView /> <!-- DataContext is known to be of correct type 
               because of DataTemplate.DataType property --> 
       </DataTemplate> 
      </ItemsControl.ItemTemplate> 
     </ItemsControl> 
    </UserControl> 

Aber zurück zur Realität. In Wirklichkeit wird alles Träumen in naher Zukunft nicht passieren.

Allerdings bin ich sicher, dass ich nicht die erste Person bin, die dieses Problem hat.
Also, schließlich ist die Frage: Wie stellen Sie sicher, dass Ihre Bindungen korrekt sind? Und dass sie so bleiben?

+0

UWP bietet nun statische Bindung über die ['{x: Bind}' Markup-Erweiterung] (https://docs.microsoft.com/en-us/windows/uwp/xaml-platform/x-bind-markup- Erweiterung). Mysteriöse Wege :) – Funk

Antwort

8

Wie sieht die statische Analyse Ihres Xaml als Post-Build-Schritt aus?

Als Teil von .Net 4 hat Microsoft eine neue System.Xaml-Bibliothek veröffentlicht, um robuste Xaml-Parsing- und Serialisierungsunterstützung unabhängig von WPF bereitzustellen. Sie fangen jetzt an, alle möglichen interessanten Dinge darüber zu bauen, von denen einige Ihnen helfen können.

In der XamlToolkit zum Beispiel finden Sie die XamlDOM, mit der Sie einfache statische Analyse von Xaml-Dateien durchführen können. Und das ein bisschen weiter gehend, gibt es FxCop rules for XAML.

Von Interesse ist Rob Relyea BindingFinder, die das explizite Ziel der Typ Überprüfung Bindungen in Xaml hat. Dies erfordert, dass Sie Typhinweise in Ihrem Xaml haben, wie das DataType-Attribut in einem DataTemplate oder das neue d:DataContext attribute in Ihren Ansichten (das Blend zum Bereitstellen von Entwurfszeitdaten verwendet). Es prüft dann mit XamlDOM, ob alles übereinstimmt.

Update:Resharper 6 bietet jetzt intellisense for data bindings und Warnungen, wenn Sie Ihre Eigentumswege falsch erhalten.

+0

... Aaaaaaaand 200 Ruf geht zu Samuel Jack! Danke, Herr, das ist fast genau das, was ich suchte. Ich war tatsächlich am Rande der Durchführung so etwas selbst, aber irgendwo anfangen zu können, ist immer besser.:-) –

+0

@Fyodor - ich bin froh, dass ich Ihnen helfen kann! –

+0

Visual Studio 2010 und XAML benötigen "BindingFinder" -Funktionalität sofort! – thenonhacker

2

Aus praktischen Gründen habe ich nie ein Problem gefunden, zumindest wenn ich das MVVM-Muster verwende. Das Ansichtsmodell existiert nur zur Unterstützung der Ansicht. Ich werde keins ändern, ohne das andere zu ändern. Das Refactoring des Ansichtsmodells wird die Bindungen in der Ansicht nicht brechen, da es keinen Sinn macht, das Ansichtsmodell um seiner selbst willen zu refaktorieren.Sie werden das Ansichtsmodell nur dann umgestalten, wenn Sie (und weil) das Design der Ansicht ändern.

Der andere Grund, warum ich dieses Problem nicht habe, ist, dass ich das Ansichtsmodell nicht unabhängig von Expression Blend entwickle. Für alle außer den trivialsten UIs baue ich meine Ansichtsmodelle mit einer Art Abhängigkeitsinjektion, sodass ich eine Testdatenquelle erstellen kann, die in Expression Blend verwendet werden kann. Wenn ich Bindungen in Blend erzeuge, weiß ich sofort, ob ich es richtig gemacht habe oder nicht.

Wie bei MVVM im Allgemeinen ist dies ein unglaublicher Schmerz in den Arsch, bis Sie verstehen, was Sie tun und warum. (This long blog post von Jonas Follesø gibt einen ziemlich guten Überblick über die Verwendung von Ninject für diesen Zweck, obwohl es kein Ende anderer Frameworks gibt, die Sie verwenden können.) Ich bin sicher, dass es Probleme gibt, die ich mit dieser Methode noch nicht aufgedeckt habe - über das Problem hinaus, dass ich DI-Frameworks und Expression Blend in den Haufen von Dingen eingefügt habe, die ich zum Entwickeln von WPF-Anwendungen verstehen muss.

Pablo Casals sagte, dass ständige Experimente den Künstler jung halten. Ich fühle mich nicht fühlen jung.

+2

Nun, es scheint, als ob wir MVVM anders verstehen. Als ich es zu verstehen begann, sollte man an ViewModel als die eigentliche Benutzeroberfläche der Anwendung denken, während View nur eine Art "Haut" für diese Benutzeroberfläche ist. Ich kann zum Beispiel diesen Artikel zitieren: http://msdn.microsoft.com/en-us/magazine/dd419663.aspx Dieser Ansatz ermöglichte ein paar nette Dinge. Zum Beispiel: Man kann mehr als eine "Haut" für die gleiche Benutzeroberfläche haben. Ein anderes Beispiel: "skin" kann relativ unabhängig von der UI selbst und auch von einer anderen Person (üblicherweise als "Designer" bezeichnet) entworfen werden :-). [weiter im nächsten Kommentar] –

+1

Ein weiteres Beispiel: Im Falle mehrerer "Skins" können einige von ihnen unabhängig voneinander, von einer anderen Person oder von einer anderen Firma oder sogar vom Kunden entworfen werden! Und natürlich, was ist mit Komponententests? Wenn ViewModel als "Unterstützung" für View angezeigt wird, sollten Sie bei der Entwicklung von Komponententests stets auf View achten. Und selbst aus Ihrer Sicht funktioniert es immer noch nicht: Wenn die View von einer anderen Person ("Designer") entworfen wird, wie werden Sie diese zusammen mit dem ViewModel ändern? –

+1

Und schließlich, in Bezug auf die Notwendigkeit für Refactoring. Ich bitte auch, mich in diesem Teil zu unterscheiden.Das Refactoring wird regelmäßig verwendet, wenn das System zu komplex wird, so dass es in einfachere Systeme zerlegt werden muss oder seine Komponenten auf andere Weise neu angeordnet werden müssen. Ein einfaches Beispiel: Angenommen, auf einem Bildschirm sollten Informationen zu einem Produkt angezeigt werden. Sprich, Name und Preis. Also hat mein ViewModel diese Eigenschaften und die Ansicht ist an sie gebunden. Dann kommt eine Anforderung: Fügen Sie ein "Hersteller" -Feld hinzu. Nur eine einfache Zeichenfolge. OK, fertig. Jetzt hat mein ViewModel eine andere Eigenschaft namens "Manufacturer". [Siehe nächste Seite] –