【问题标题】:WPF : Re-usable template for image buttons?WPF:图像按钮的可重用模板?
【发布时间】:2013-08-28 07:30:44
【问题描述】:

我的 WPF 项目使用了很多图像按钮,但是由于我没有找到正确的方法(我每次都必须编写相同的触发器和样式,唯一的区别是图像源),我的资源字典变得很长,一无所获。有更好的方法吗?

这是我用于按钮的样式示例:

<Style x:Key="ButtonStyle" TargetType="{x:Type Button}">
    <!-- Some setters -->
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Grid>
                    <Image Source="Images.png" Stretch="Fill"/>
                </Grid>
                <ControlTemplate.Triggers>
                    <!-- Some triggers ( IsFocused, IsMouseOver, etc.) -->
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

谢谢你:)

【问题讨论】:

    标签: c# wpf button


    【解决方案1】:

    最简单的方法是使用Image 属性创建特定控件:

    public class ImageButton : Button
    {
        static ImageButton()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof (ImageButton),
                new FrameworkPropertyMetadata(typeof (ImageButton)));
        }
    
    
        public ImageSource Image
        {
            get { return (ImageSource)GetValue(ImageProperty); }
            set { SetValue(ImageProperty, value); }
        }
    
        public static readonly DependencyProperty ImageProperty =
            DependencyProperty.Register("Image", typeof(ImageSource), typeof(ImageButton), new PropertyMetadata(default(ImageSource)));
    
    }
    

    然后您只需在 generic.xaml 中为其创建样式,并绑定到 Image 属性,而不是显式设置图像:

    <Style x:Key="{x:Type my:ImageButton}" TargetType="{x:Type my:ImageButton}">
        <!-- Some setters -->
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type my:ImageButton}">
                    <Grid>
                        <Image Source="{TemplateBinding Image}" Stretch="Fill"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <!-- Some triggers ( IsFocused, IsMouseOver, etc.) -->
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    

    那么你可以像这样使用它:

    <my:ImageButton Image="Image.png" />
    

    如果按钮的不同状态需要更多图片,可以为控件添加更多依赖属性。

    另一种可能的方法是使用我所说的“参数化样式”,以避免创建特定控件;详情请见this blog post

    【讨论】:

    • 谢谢,正是我需要的!
    • 这个例子展示了 WPF 中自定义控件的一个主要问题。一旦我覆盖 ControlTemplate,所有主题基本上都被破坏了。如何在所有环境下保留原始按钮的所有主题?当然,我可以将 Button 的原始 ControlTemplate 复制到我的 ImageButton 中,但这仅适用于通用主题。我必须为我想要支持的所有主题提供控制模板。但是,如果有一个我不知道的主题,这就会中断。
    • @bitbonk,是的,这是这个模板系统的主要缺点之一......不幸的是,我不知道有什么好的解决方案。
    • @ThomasLevesque 指向“this blog post”的链接指向这个 StackOverflow 问题,而不是指向博客帖子 :(
    • @ThomasLevesque 另外,XAML sn-p 的第 5 行是否不应该包含 {x:Type my:ImageButton} 而不是 {x:Type Button}?我收到“无法识别或无法访问该成员”错误,但通过此更改,一切正常。
    【解决方案2】:

    您可以尝试创建一个继承自 Button 的自定义控件,并将其用作模板中的 TargetType。然后您可以在 Image Source 中使用 TemplateBinding。

    <Image Source="{TemplateBinding ImageSource}" Stretch="Fill"/>
    

    您需要在自定义控件中创建 ImageSource 属性。 这样你可以在xaml中设置源,但你只需要一个资源模板。

    【讨论】:

      【解决方案3】:

      您可以像这样使用 BasedOn 属性:

      <Style x:Key="BlueHighlightedButtonStyle"  BasedOn="{StaticResource ButtonStyle}" TargetType="Button">
          <Setter Property="Background" Value="DeepSkyBlue"/>
      </Style>
      

      这将使按钮样式与您的按钮样式具有相同的属性,但具有深天蓝色背景。

      【讨论】:

      • 唯一的问题是 BaseOn 属性不适用于所有触发器,我想避免每次添加不同按钮时重新定义它们。我尝试在 ControlTemplate 中使用 TemplateBinding,但没有成功。
      猜你喜欢
      • 2017-11-16
      • 2012-07-15
      • 2010-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-13
      • 2011-09-08
      • 1970-01-01
      相关资源
      最近更新 更多