Come parametrizzare WPF Style?
-
20-09-2019 - |
Domanda
Sto cercando un modo più semplice per eliminare la duplicazione nel mio codice WPF.
Codice di seguito è un semplice semaforo con 3 luci - Red
, Amber
, Green
. Si è associato a un ViewModel che ha un'enum proprietà State
prendere uno di quei 3 valori.
Codice dichiarando 3 ellissi è molto duplicazione. Ora voglio aggiungere l'animazione in modo che ogni luce svanisce dentro e fuori -. Stili diventeranno ancora più grande e la duplicazione destinata a peggiorare
E 'possibile parametrizzare stile con State
e Color
argomenti in modo che io possa avere un unico stile di risorse che descrivono il comportamento di una luce e poi usarlo per 3 volte - per 'Red', 'Ambra' e luci 'verde'?
<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>
Soluzione
Fino a quando il "Traffic Light" è avvolto all'interno di un controllo, che appare è, io non credo che questo è orribile. Ogni ellisse è ben definito e ha diversi trigger, ciascuno indicante il suo stato. Hai già scontato le parti comuni fuori nel stile di base, che è buono.
Si potrebbe avvolgere i singoli puntini di sospensione all'interno di un altro controllo utente (che non avrebbe bisogno di un supporto ViewModel) che aveva una proprietà ActiveState
e una proprietà ActiveFill
. Allora la vostra TrafficLight sembra qualcosa di simile:
<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>
Questo consente di avvolgere tutto il vostro stile di ellisse all'interno del vostro controllo indicatore e l'unica cosa che di controllo deve preoccupare è confrontando il State
al ActiveState
per determinare se deve riempirsi con il pennello ActiveFill
.
Per quanto riguarda se questo vale la pena o no, che dipende da quanti di questi si è galleggianti intorno e se li usate al di fuori del controllo utente Traffic Light. Ricordate: you are not gonna need it
.