2009-03-09 7 views
4

Betrachten wir die Folge 2 XAML-Schnipsel (die Seite an Seite in der Datei) Vermeidung von Doppel:in WPF (nach DRY)

<Button 
    x:Name="BuyButton" 
    Margin="0,0,1,1" 
    IsEnabled="{Binding CanBuy}" 
    > 
    <StackPanel 
     DataContext="{Binding Product}"> 
     <TextBlock 
      Foreground="Red" 
      Text="BUY" /> 
     <TextBlock 
      Foreground="Red" 
      Text="{Binding BuyPrice}" /> 
    </StackPanel> 
    </Button> 

<Button 
    x:Name="SellButton" 
    Margin="0,0,1,1" 
    IsEnabled="{Binding CanSell}" 
    > 
    <StackPanel 
     DataContext="{Binding Product}"> 
     <TextBlock 
      Foreground="Red" 
      Text="SELL" /> 
     <TextBlock 
      Foreground="Red" 
      Text="{Binding SellPrice}" /> 
    </StackPanel> 
</Button> 

Wie man nicht entfernen Vervielfältigung in WPF? Ich habe ca. 4 Anwendungen (2 hier gezeigt) dieser Art von Button, und sie sind 80% gleich, wenn nicht mehr. Ich könnte dies in ein Benutzersteuerelement extrahieren und ein paar DPs darauf setzen, und dann hätte ich eine Kontrolle, aber ich befürchte, dass ich anfangen werde, meine Codebasis mit Tonnen von Benutzersteuerelementen zu verschütten (ich habe viele "einmalige") "Situationen wie diese). Ich mag die DataTemplate-Lösung hier nicht, da ich immer noch zwei Vorlagen benötige, die Code hätten wiederholen müssen. Ohne eine Reihe von Vorlagen/Steuerelementen zu erstellen, gibt es eine Möglichkeit, diesen Code DRY folgen zu lassen?

Antwort

2

Ich habe keine alternative Lösung, aber ich stimme nicht zu Ihrem Argument der einmaligen Kontrollen. Meiner Meinung nach läuft es darauf hinaus, zwischen einer Menge von doppeltem Code oder weniger Duplizierung mit einer Anzahl von Kontrollen zu wählen, die ziemlich spezifisch sind. Wenn dies einfacher Code wäre, würden Sie wahrscheinlich nicht zweimal darüber nachdenken, eine Extraktionsmethode durchzuführen, wenn Sie mit mehreren Blöcken identischen Codes konfrontiert werden. Warum ist die Tatsache, dass dieser Code nun XAML ist, Ihre Entscheidung anders?

+0

Aus dem Stand kann ich schnell sagen, weil ich keine neue Datei mit Extrakt-Methode erstellen muss. Aber ja, ich verstehe Ihre Argumentation, hatte einen ähnlichen internen Dialog. – DavidN

0

Trennen Sie es in ein Benutzersteuerelement. DRY-Prinzipien und Refactoring sollten auf nahezu jeder Plattform gleich behandelt werden.

2

Wenn Ihr Ziel nur Wiederholungen zu reduzieren, können Sie eine Menge davon eliminieren durch Stile und die Festlegung gemeinsamer angefügten Eigenschaften für ein übergeordnetes Element mit:

<StackPanel> 
    <StackPanel.Resources> 
     <Style TargetType="{x:Type Button}"> 
      <Setter Property="Margin" Value="0,0,1,1"/> 
     </Style> 
     <Style TargetType="{x:Type TextBlock}"> 
      <Setter Property="Foreground" Value="Red"/> 
      <Setter Property="DataContext" Value="{Binding Product}"/> 
     </Style> 
    </StackPanel.Resources> 
    <Button x:Name="BuyButton" IsEnabled="{Binding CanBuy}"> 
     <StackPanel> 
      <TextBlock Text="BUY"/> 
      <TextBlock Text="{Binding BuyPrice}"/> 
     </StackPanel> 
    </Button> 
    <Button x:Name="SellButton" IsEnabled="{Binding CanSell}"> 
     <StackPanel> 
      <TextBlock Text="SELL"/> 
      <TextBlock Text="{Binding SellPrice}"/> 
     </StackPanel> 
    </Button> 
</StackPanel> 

Beachten Sie, dass dies mehr Code endet als .. Deshalb ist "3 strikes, dann refactor" die Faustregel.

3

A Control funktionieren könnte:

<ControlTemplate x:Key="ButtonControlTemplate1" TargetType="{x:Type Button}"> 
<StackPanel Height="Auto" Width="Auto"> 
    <TextBlock Text="{TemplateBinding Content}" Foreground="Red"/> 
    <TextBlock Text="{TemplateBinding Tag}" Foreground="Red"/> 
</StackPanel></ControlTemplate> 

I verwendet Template die beiden veränderbare Teile der Daten zu bekommen. Nun, wenn Sie auf die Schaltfläche erstellen, wenden Sie die Vorlage, und stellen Sie die Bindungen auf Ihre Elemente:

<Button x:Name="BuyButton" 
    Margin="0,0,1,1" 
    IsEnabled="{Binding CanBuy}" 
    Template="{DynamicResource ButtonControlTemplate1}" 
    Content="Button" 
    Tag="{Binding BuyPrice}"/> 

Das einzige, was fehlt, ist die Datacontext: nur an einem Behälter legen Sie es über den beiden Tasten.

Ich habe es nicht speziell versucht, aber es scheint, es sollte funktionieren. Ich habe oben "Tag" gewählt, weil ich ein zweites Element für Binding benötigte. Ich würde gerne verschiedene Vorschläge dazu sehen.

Sie möchten wahrscheinlich auch den ForegroundColor = "Red" -Typ Zeug in einen Stil zu brechen.

+0

Für 2 Elemente, ja Ihre Wahl von "Tag" wird funktionieren. Mit 3 Elementen sind wir jetzt wieder auf Platz eins (ich glaube nicht, dass ein MultiBinding auf Tag wünschenswert wäre;)). Irgendwelche anderen Vorschläge zu diesem spezifischen Problem? – DavidN

+0

Leider habe ich das nicht, weshalb ich auf weitere Kommentare zu diesem Ansatz gehofft hatte. Ich frage mich, ob Sie ein anderes ControlTemplate in den Button-Inhalt einfügen könnten und dann irgendwie in der TemplateBinding navigieren könnten? –