Change WPF button background image programmatically

前端 未结 2 1394
野趣味
野趣味 2021-01-14 11:11

I\'m trying to create a

相关标签:
2条回答
  • 2021-01-14 11:41

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

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

    Option 1: Place the Image as 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 Tag Property:

    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 Tag property.

            <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

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

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

    Option 4: Create a Custom Control:

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

    Option 5: MVVM

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

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

    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.

    0 讨论(0)
  • 2021-01-14 11:42

    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

    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

    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?

    0 讨论(0)
提交回复
热议问题