以编程方式更改 WPF 按钮背景图像

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15819796/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 08:28:21  来源:igfitidea点击:

Change WPF button background image programmatically

c#wpfxaml

提问by David Murdoch

I'm trying to create a <Button/>with a png image for the background AND a background color.

我正在尝试<Button/>为背景和背景颜色创建一个带有 png 图像的图像。

Note:The png imagesource may not yet be known, so I can't just put them in the template.

注:PNG图像源可能还不知道,所以我不能只是把他们的模板。

I've got a Stylethat looks like this:

我有一个Style看起来像这样的:

<Style x:Key="MyButton" TargetType="Button">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <Border CornerRadius="0">
                    <Image Margin="0" Source="/MyApp;component/Images/my-image.png" Stretch="None" />
                    <Border.Style>
                        <Style TargetType="{x:Type Border}">
                            <Setter Property="Background" Value="LimeGreen" />
                        </Style>
                    </Border.Style>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

which gives me a button with a png image on top of a solid LimeGreen background.

这给了我一个在纯 LimeGreen 背景上带有 png 图像的按钮。

My MainWindow.xamllooks somewhat like this:

我的MainWindow.xaml看起来有点像这样:

<Button Style="{StaticResource MyButton}" Click="btnMine_Click" /* some other props */ />

and the code behind it is like this:

而其背后的代码是这样的:

private void btnMine_Click(object sender, RoutedEventArgs e)
{
    // TODO: change the image src on this button
    var myButton = sender as Button;

    // This won't work:
    // myButton.Border.Image.Source = getNewImageString();
}

How do I change the image source from /MyApp2;component/Images/my-image.pngto something else?

如何将图像源从/MyApp2;component/Images/my-image.png其他内容更改?

采纳答案by Federico Berasategui

Sigh, in Windows Forms it was literally one line. In WPF it looks like it will be several hundred.

唉,在 Windows 窗体中,它实际上是一行。在 WPF 中,它看起来像是几百个。

That's because it was the ONLY thing you could place in a button in winforms. WPF is a true UI framework, not some random semi-deprecated dinosaur that only allows to do the default stuff (which by the way looks horrible).

那是因为它是唯一可以放在 winforms 按钮中的东西。WPF 是一个真正的 UI 框架,而不是一些随机的、半弃用的恐龙,它只允许做默认的东西(顺便说一下,这看起来很可怕)。

Option 1: Place the Image as Button's Content:

选项 1:将图像放置为 Button's Content

If you just want to place an Image in the button, and nothing else, why not just do that?

如果您只想在按钮中放置一个图像,而别无其他,为什么不这样做呢?

        <Style TargetType="Button">
            <Setter Property="Background" Value="LimeGreen"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="Button">
                        <Border Background="{TemplateBinding Background}">
                            <ContentPresenter ContentSource="Content"/>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

Then:

然后:

     <Button>
        <!-- Background not set, defaults to what's set in the Style -->
        <Image Source="./ChessPieces/BlackKnight.png"/>
    </Button>
    <Button Background="Red">
        <Image Source="./ChessPieces/BlackBishop.png"/>
    </Button>
    <Button Background="Blue">
        <Image Source="./ChessPieces/BlackPawn.png"/>
    </Button>

    <!-- WPF's idea of "Dynamic" is not the same as win(hack)forms' -->
    <Button Background="White">
        <Image Source="{Binding SomeStringPropertyDefinedInAViewModel}"/>
    </Button>

Result:

结果:

enter image description here

在此处输入图片说明

Option 2 (not very elegant): Use the TagProperty:

选项 2(不是很优雅):使用Tag属性:

If, in addition to the Image, you want to put something else inside the Button, you can resort to a somewhat hacky approach of putting the ImageSource in the Button's Tagproperty.

如果除了 Image 之外,您还想在 Button 中放置其他东西,您可以采用一种有点老套的方法,将 ImageSource 放在 Button 的Tag属性中。

        <Style TargetType="Button">
            <Setter Property="Background" Value="LimeGreen"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="Button">
                        <Border Background="{TemplateBinding Background}">
                            <StackPanel Orientation="Horizontal">
                                <Image Source="{Binding Tag, RelativeSource={RelativeSource TemplatedParent}}"
                                       Height="50" Width="50"/>
                                <ContentPresenter ContentSource="Content"/>
                            </StackPanel>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

Then:

然后:

    <Button Tag="./ChessPieces/BlackKnight.png"
            Background="Blue"
            Foreground="White"
            Content="Some Text"/>

    <Button Tag="./ChessPieces/BlackBishop.png"
            Background="LightGray">
        <CheckBox Content="A CheckBox!" VerticalAlignment="Center"/>
    </Button>

Result:

结果:

enter image description here

在此处输入图片说明

Option 3: Use an Attached Property

选项 3:使用附加属性

Same as option 2, but using a property declared elsewhere, for example:

与选项 2 相同,但使用在别处声明的属性,例如:

 <Button ButtonImage.Source="./ChessPieces/BlackBishop.png"
         <!-- etc -->

Option 4: Create a Custom Control:

选项 4:创建自定义控件:

Create a class (.cs file with no XAML) derived from Button and add a DependencyPropertyto hold the image, then set the template to that and use that value.

创建一个派生自 Button 的类(没有 XAML 的 .cs 文件)并添加一个DependencyProperty来保存图像,然后将模板设置为该类并使用该值。

Option 5: MVVM

选项 5:MVVM

Create a ButtonViewModel, or actually use a DelegateCommanddeclared in the ViewModel to bind the Button's properties.

创建一个ButtonViewModel,或者实际使用在 ViewModel 中声明的DelegateCommand来绑定 Button 的属性。

Not an Option: Traverse the Visual Tree and change the Image.Sourcein code.

不是一个选项:遍历可视化树并更改Image.Source代码。

That's not something you will want to do. It's not a good approach at all.

这不是你想做的事情。这根本不是一个好方法。

I could go on forever, but I have to go to sleep. If you want me to elaborate on any of these approaches just let me know.

我可以一直走下去,但我必须去睡觉。如果您想让我详细说明这些方法中的任何一种,请告诉我。

回答by Clint

A few ways spring to mind:

有几种方法浮现在脑海中:

  1. Access the style at runtime and traverse it to find the image
  2. Give the image a name and reference that at runtime and just change the source
  1. 在运行时访问样式并遍历它以找到图像
  2. 在运行时为图像命名和引用,只需更改源

The best solution I believe is to create a usercontrol and have the image source as a dependency property see: http://www.codeproject.com/Articles/224230/Exploring-the-use-of-Dependency-Properties-in-User

我认为最好的解决方案是创建一个用户控件并将图像源作为依赖属性,请参见:http: //www.codeproject.com/Articles/224230/Exploring-the-use-of-Dependency-Properties-in-User

That way you'll have a ready-to-use "custom" control that supports what you're after and allows you to just reference it directly and use bindings, that way you avoid the messy solutions from using a style.

这样,您将拥有一个随时可用的“自定义”控件,该控件支持您所追求的内容,并允许您直接引用它并使用绑定,这样您就可以避免使用样式的混乱解决方案。



After discussion and expansion on requirements, please see:

需求讨论和扩展后,请参见:

How can I access ResourceDictionary in wpf from C# code?

如何从 C# 代码访问 wpf 中的 ResourceDictionary?