如何在WPF xaml中参数化按钮样式

时间:2018-02-06 14:55:36

标签: wpf xaml

我尝试创建一个具有特定效果的模板按钮,该按钮可以接收2个背景图像作为参数(按下按钮和释放按钮)。此模板在用户控件库中实现:

                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:local="clr-namespace:SwitchesLibrary">
<Style x:Key="PushButton" TargetType="Button">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <Grid>
                    <Border x:Name="MyBorder" CornerRadius="5" Background="{TemplateBinding Background}" BorderThickness="1">
                        <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
                    </Border>
                    <Border x:Name="ButtonPressedOnClick" Opacity="0" CornerRadius="5" Background="{DynamicResource ButtonPressed}" BorderThickness="1">
                    </Border>
                </Grid>
                <ControlTemplate.Triggers>
                    <EventTrigger RoutedEvent="Button.Click">
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimationUsingKeyFrames Storyboard.TargetName="ButtonPressedOnClick" Storyboard.TargetProperty="(FrameworkElement.Opacity)">
                                    <EasingDoubleKeyFrame KeyTime="0:0:0.05" Value="1.0"/>
                                    <EasingDoubleKeyFrame KeyTime="0:0:1" Value="0.0"/>
                                </DoubleAnimationUsingKeyFrames>
                                <DoubleAnimationUsingKeyFrames Storyboard.TargetName="MyBorder" Storyboard.TargetProperty="(FrameworkElement.Opacity)">
                                    <EasingDoubleKeyFrame KeyTime="0:0:0.05" Value="0.0"/>
                                    <EasingDoubleKeyFrame KeyTime="0:0:1" Value="1.0"/>
                                </DoubleAnimationUsingKeyFrames>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Setter Property="Background" Value="{DynamicResource ButtonReleased}"/>
</Style>

我在其他用户控件库中使用它,但我不知道如何发送参数{DynamicResource ButtonReleased}{DynamicResource ButtonPushed}

<UserControl.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="pack://application:,,,/SwitchesLibrary;component/PushButton.xaml"></ResourceDictionary>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</UserControl.Resources>
    <Button Name="ButtonA" Style="{StaticResource PushButton, ButtonPressed="Images/PushButtons/A_Pushed.png", ButtonReleased="Images/PushButtons/A_Released.png"}" HorizontalAlignment="Left" Height="44" VerticalAlignment="Top" Width="42" Click="ButtonA_Click" Margin="69,112,0,0"/>

1 个答案:

答案 0 :(得分:1)

“参数化”Style的最接近的解决方案是覆盖Button本身中的图像资源,但这样做会相当冗长和繁琐多次:

<Button Style="{StaticResource PushButton}">
  <Button.Resources>
    <ImageBrush x:Key="ButtonPressed"
                ImageSource="Images/PushButtons/A_Pushed.png" />
    <ImageBrush x:Key="ButtonReleased"
                ImageSource="Images/PushButtons/A_Released.png" />
  </Button.Resources>
</Button>

如果您要使用的次数超过两次,则需要预先投入更多时间,以使您的图像按钮更易于使用。输入这个不是​​更方便吗?

<l:ImageButton NormalImage="Images/PushButtons/A_Released.png"
               PressedImage="Images/PushButtons/A_Pushed.png" />

如果您喜欢它的外观,那么第一步是编写一个简单的ImageButton类,并为代表各种按钮状态的图像定义依赖属性:

public class ImageButton : Button
{
    public static readonly DependencyProperty NormalImageProperty =
        DependencyProperty.Register(
            "NormalImage",
            typeof(ImageSource),
            typeof(ImageButton),
            new PropertyMetadata(default(ImageSource)));

    public ImageSource NormalImage
    {
        get { return (ImageSource)GetValue(NormalImageProperty); }
        set { SetValue(NormalImageProperty, value); }
    }

    public static readonly DependencyProperty PressedImageProperty =
        DependencyProperty.Register(
            "PressedImage",
            typeof(ImageSource),
            typeof(ImageButton),
            new PropertyMetadata(default(ImageSource)));

    public ImageSource PressedImage
    {
        get { return (ImageSource)GetValue(PressedImageProperty); }
        set { SetValue(PressedImageProperty, value); }
    }

    static ImageButton()
    {
        DefaultStyleKeyProperty.OverrideMetadata(
            typeof(ImageButton),
            new FrameworkPropertyMetadata(typeof(ImageButton)));
    }
}

第二步是为ImageButton定义默认样式。为此,请在声明Themes\Generic.xaml的项目中创建ImageButton资源字典。确保在“属性”窗格中将“构建操作”设置为“页面”。在此处实现您的默认样式,例如:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:l="clr-namespace:TestApp">

  <Style TargetType="l:ImageButton"
         BasedOn="{StaticResource {x:Type Button}}">
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="l:ImageButton">
          <Border BorderBrush="{TemplateBinding BorderBrush}"
                  BorderThickness="{TemplateBinding BorderThickness}">
            <Grid>
              <Image x:Name="image"
                     Source="{TemplateBinding NormalImage}"
                     Stretch="None"
                     HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                     VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
              <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
            </Grid>
          </Border>
          <ControlTemplate.Triggers>
            <Trigger Property="IsPressed" Value="True">
              <Setter TargetName="image"
                      Property="Source"
                      Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=PressedImage}" />
            </Trigger>
          </ControlTemplate.Triggers>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>

</ResourceDictionary>

检查项目的AssemblyInfo.cs文件并确保您拥有这样的属性(如果不这样做,则添加它):

[assembly: ThemeInfo(
    // Where theme specific resource dictionaries are located
    // (used if a resource is not found in the page, or application
    // resource dictionaries)
    ResourceDictionaryLocation.None,

    // Where the generic resource dictionary is located
    // (used if a resource is not found in the page, app, or 
    // any theme specific resource dictionaries)                                 
    ResourceDictionaryLocation.SourceAssembly 
)]

现在你准备好了!

<l:ImageButton NormalImage="Images/PushButtons/A_Released.png"
               PressedImage="Images/PushButtons/A_Pushed.png" />