如何从控件模板创建通用背景图像绑定?

时间:2012-03-07 11:35:06

标签: wpf

我有这种风格的按钮:

<Style TargetType="Button" x:Key="btnStyle">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="Button">
                            <Image x:Name="img" Source="{TemplateBinding Tag}" Margin="{TemplateBinding Margin}"
                                 Stretch="None"></Image>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsPressed" Value="true">
                                    <Setter TargetName="img" Property="Source" Value="{DynamicResource imgClose_P}"/>
                                 </Trigger>
                                <Trigger Property="IsMouseOver" Value="true">
                                    <Setter TargetName="img" Property="Source" Value="{DynamicResource imgClose_H}"/>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>

正如您所看到的,我将ImageSource绑定到按钮的Tag属性。 在Tag属性中,我将它绑定到存储此位图的ResourceDictionary:

<BitmapImage x:Key="imgClose_N" UriSource="..\AppImages\mainWindow\TopBanner\CloseButton_sN.png" />

这使我能够使用这个&#34; Imagebutton&#34;在整个应用程序中使用不同的背景图像和一个模板。 问题是如何使用触发器保持这种通用方法? 我想IsMouseOver触发器更改背景图像,但将其绑定到控件的某些属性,而不是在控件模板中硬编码。 怎么办呢?

1 个答案:

答案 0 :(得分:2)

正如您已经建议的那样,将其称为“图像按钮”,您可以从Button派生并定义一些要绑定的图像属性,例如: BackgroundImageMouseOverImage

Button派生的替代方法是使用attached properties设置图像并绑定到您的样式中的图像,但这些附加属性也必须在某处定义,而不是让它更简单。

以下是第一个解决方案的示例:

public class ImageButton : Button
{
    public static readonly DependencyProperty NormalBackgroundImageProperty = DependencyProperty.Register(
        "NormalBackgroundImage", typeof(ImageSource), typeof(ImageButton));

    public static readonly DependencyProperty MouseOverBackgroundImageProperty = DependencyProperty.Register(
        "MouseOverBackgroundImage", typeof(ImageSource), typeof(ImageButton));

    public static readonly DependencyProperty PressedBackgroundImageProperty = DependencyProperty.Register(
        "PressedBackgroundImage", typeof(ImageSource), typeof(ImageButton));

    public ImageSource NormalBackgroundImage
    {
        get { return (ImageSource)GetValue(NormalBackgroundImageProperty); }
        set { SetValue(NormalBackgroundImageProperty, value); }
    }

    public ImageSource MouseOverBackgroundImage
    {
        get { return (ImageSource)GetValue(MouseOverBackgroundImageProperty); }
        set { SetValue(MouseOverBackgroundImageProperty, value); }
    }

    public ImageSource PressedBackgroundImage
    {
        get { return (ImageSource)GetValue(PressedBackgroundImageProperty); }
        set { SetValue(PressedBackgroundImageProperty, value); }
    }
}

以及下面的合适款式。请注意,此样式对按钮的内容也有ContentPresenter,并且它使用RelativeSource={RelativeSource TemplatedParent}而不是TemplateBindings的常规绑定。这些是在运行时评估的。

<Style TargetType="local:ImageButton">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:ImageButton">
                <Grid Margin="{TemplateBinding Margin}">
                    <Image x:Name="img" Source="{Binding NormalBackgroundImage, RelativeSource={RelativeSource TemplatedParent}}" Stretch="None"/>
                    <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="true">
                        <Setter TargetName="img" Property="Source" Value="{Binding MouseOverBackgroundImage, RelativeSource={RelativeSource TemplatedParent}}"/>
                    </Trigger>
                    <Trigger Property="IsPressed" Value="true">
                        <Setter TargetName="img" Property="Source" Value="{Binding PressedBackgroundImage, RelativeSource={RelativeSource TemplatedParent}}"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

您必须使用包含类local的命名空间/程序集的映射来定义或替换XAML名称空间ImageButton

按钮可以像这样使用:

<local:ImageButton
    Margin="10"
    NormalBackgroundImage="C:\Users\Public\Pictures\Sample Pictures\Desert.jpg"
    PressedBackgroundImage="C:\Users\Public\Pictures\Sample Pictures\Tulips.jpg"
    MouseOverBackgroundImage="C:\Users\Public\Pictures\Sample Pictures\Penguins.jpg"
    Content="Click Me"/>