如何参数化WPF样式?

时间:2010-03-17 04:08:41

标签: wpf styles code-duplication

我正在寻找一种最简单的方法来删除我的WPF代码中的重复。

以下代码是一个简单的红绿灯,有3个灯光 - RedAmberGreen。它绑定到一个ViewModel,它有一个枚举属性State从中获取这三个值中的一个。

声明3个省略号的代码非常重复。现在我想添加动画,以便每个灯光渐入淡出 - 样式会变得更大,重复会变差。

是否可以使用StateColor参数对样式进行参数化,以便我可以在描述灯光行为的资源中使用单一样式,然后使用它3次 - 对于“红色”,“琥珀'和'绿'灯?

<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>

1 个答案:

答案 0 :(得分:1)

只要你的“交通信号灯”被包裹在一个控制器里面,它看起来就是这样,我认为这并不可怕。每个椭圆都被很好地定义并具有不同的触发器,每个触发器指示其自己的状态你已经将常见的部分考虑到了基本风格中,这很好。

您可以将单个省略号包装在另一个具有ActiveState属性和ActiveFill属性的用户控件(不需要支持ViewModel)中。然后你的TrafficLight看起来像:

<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>

这使您可以在指标控件中包含所有Ellipse样式,控件唯一需要担心的是将StateActiveState进行比较,以确定它是否应该填充自己ActiveFill刷。

至于这是否值得付出努力,这取决于你有多少这些,如果你在Traffic Light用户控件之外使用它们。记住:你不需要它。