2010-03-17 4 views
1

Je suis à la recherche d'un moyen simple pour supprimer la duplication dans mon code WPF. Le code ci-dessous est un feu de signalisation simple avec 3 feux - Red, Amber, Green. Il est lié à un ViewModel qui possède une propriété enum State prenant une de ces 3 valeurs.Comment paramétrer WPF Style?

Le code déclarant 3 ellipses est très duplicatif. Maintenant, je veux ajouter une animation pour que chaque lumière disparaisse et disparaisse - les styles deviendront encore plus gros et la duplication s'aggravera.

Est-il possible de paramétrer le style avec les arguments State et Color afin que je puisse avoir un seul style dans les ressources décrivant le comportement d'une lumière et l'utiliser 3 fois - pour les lumières 'Rouge', 'Ambre' et 'Vert' ?

<UserControl.Resources> 
    <l:TrafficLightViewModel x:Key="ViewModel" /> 
</UserControl.Resources> 

<StackPanel Orientation="Vertical" DataContext="{StaticResource ViewModel}"> 
    <StackPanel.Resources> 
     <Style x:Key="singleLightStyle" TargetType="{x:Type Ellipse}"> 
      <Setter Property="StrokeThickness" Value="2" /> 
      <Setter Property="Stroke" Value="Black" /> 
      <Setter Property="Height" Value="{Binding Width, RelativeSource={RelativeSource Self}}" /> 
      <Setter Property="Width" Value="60" /> 
      <Setter Property="Fill" Value="LightGray" /> 
     </Style> 
    </StackPanel.Resources> 

    <Ellipse> 
     <Ellipse.Style> 
      <Style TargetType="{x:Type Ellipse}" BasedOn="{StaticResource singleLightStyle}"> 
       <Style.Triggers> 
        <DataTrigger Binding="{Binding State}" Value="Red"> 
         <Setter Property="Fill" Value="Red" /> 
        </DataTrigger> 
       </Style.Triggers> 
      </Style> 
     </Ellipse.Style> 
    </Ellipse> 
    <Ellipse> 
     <Ellipse.Style> 
      <Style TargetType="{x:Type Ellipse}" BasedOn="{StaticResource singleLightStyle}"> 
       <Style.Triggers> 
        <DataTrigger Binding="{Binding State}" Value="Amber"> 
         <Setter Property="Fill" Value="Red" /> 
        </DataTrigger> 
       </Style.Triggers> 
      </Style> 
     </Ellipse.Style> 
    </Ellipse> 
    <Ellipse> 
     <Ellipse.Style> 
      <Style TargetType="{x:Type Ellipse}" BasedOn="{StaticResource singleLightStyle}"> 
       <Style.Triggers> 
        <DataTrigger Binding="{Binding State}" Value="Green"> 
         <Setter Property="Fill" Value="Green" /> 
        </DataTrigger> 
       </Style.Triggers> 
      </Style> 
     </Ellipse.Style> 
    </Ellipse> 
</StackPanel> 

Répondre

1

Tant que votre « Traffic Light » est enveloppé dans un contrôle, ce qui semble qu'il est, je ne pense pas que ce soit horrible. Chaque ellipse est bien définie et a des déclencheurs différents, chacun indiquant son propre état. Vous avez déjà pris en compte les parties communes dans le style de base, ce qui est bien.

Vous pouvez placer les ellipses individuelles à l'intérieur d'un autre contrôle utilisateur (qui n'aurait pas besoin d'un ViewModel de support) ayant une propriété ActiveState et une propriété ActiveFill. Ensuite, votre TrafficLight ressemble à quelque chose comme:

<StackPanel Orientation="Vertical" DataContext="{StaticResource ViewModel}"> 
    <my:Indicator State="{Binding State}" ActiveState="Red" ActiveFill="Red" /> 
    <my:Indicator State="{Binding State}" ActiveState="Amber" ActiveFill="Red" /> 
    <my:Indicator State="{Binding State}" ActiveState="Green" ActiveFill="Green" /> 
</StackPanel> 

Cela vous permet d'envelopper tout votre style Ellipse dans le contrôle de votre indicateur et la seule chose qui contrôle doit inquiéter pour comparer le State au ActiveState pour déterminer si elle doit remplir lui-même avec le pinceau ActiveFill. Quant à savoir si cela en vaut la peine ou non, cela dépend du nombre de ceux-ci que vous avez autour et si vous les utilisez en dehors de votre contrôle utilisateur Traffic Light. Rappelez-vous: vous n'en aurez pas besoin.

+0

J'ai pensé à créer un contrôle séparé, mais j'espérais qu'il y aurait un autre moyen d'éliminer la duplication. Merci d'avoir répondu! –