BSchlinker
BSchlinker

Reputation: 3481

Programmatically changing button icon in WPF

I currently have a button, which has an icon/image on it. I have configured the button and image in XAML:

<Button Height="69" HorizontalAlignment="Left" Margin="-2,0,0,0" Name="toggleBroadcast" VerticalAlignment="Top" Width="64" Grid.Row="1" Opacity="0.5" Click="changeBroadcastState_Click">
        <Image Source="Images\playIcon.png" />
</Button>

I need to be able to programmatically change this button's image from playIcon to stopIcon. How can I do this?

Upvotes: 22

Views: 53494

Answers (5)

Tsjakka
Tsjakka

Reputation: 81

I used the other answers in this topic to puzzle together the solution I needed for my MVVM application. The code is used to flip the image and tooltip of a toolbar button (Hide/Unhide in this case). It might help you if I put it all together here. First, the declaration of the button in the xaml file:

<Button ToolTip="{Binding ButtonText}">
    <Image Height="32" Width="32" Source="{Binding ButtonImage}"/>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Click">
        <i:CallMethodAction TargetObject="{Binding}" MethodName="HideAction"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</Button>

In my ViewModel class, I declared:

private BitmapImage _buttonImage;

public BitmapImage ButtonImage
{
    get { return _buttonImage; }
    set
    {
        _buttonImage = value;
        OnPropertyChanged("ButtonImage");
    }
}

private string _buttonText;

public string ButtonText
{
    get { return _buttonText; }
    set
    {
        _buttonText = value;
        OnPropertyChanged("ButtonText");
    }
}

Here the code for the event handler that changes the button:

public void HideAction()
{
    // Hide the thing you want to hide
    ...

    // Flip the button
    if (ButtonText == "Hide")
    {
        ButtonImage = new BitmapImage(new Uri(@"pack://application:,,,/Resources/Unhide32.png", UriKind.RelativeOrAbsolute));
        ButtonText = "Unhide";
    }
    else
    {
        ButtonImage = new BitmapImage(new Uri(@"pack://application:,,,/Resources/Hide32.png", UriKind.RelativeOrAbsolute));
        ButtonText = "Hide";
    }
}

In the constructor of my ViewModel class I initialize the image and tooltip:

ButtonImage = new BitmapImage(new Uri(@"pack://application:,,,/Resources/Hide32.png", UriKind.RelativeOrAbsolute));
ButtonText = "Hide";

Upvotes: 0

d.moncada
d.moncada

Reputation: 17392

You can accomplish this by changing the content of the button, through an event handler.

You can set both the "Play" Icon and "Stop" Icon as a resource, under Window.Resources like so:

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<Window.Resources>
    <Image x:Key="Play" Source="/WpfApplication1;component/Play_Icon.png" Height="50" Width="50" />
    <Image x:Key="Stop" Source="/WpfApplication1;component/Stop_Icon.png" Height="50" Width="50"/>
</Window.Resources>
<Grid>
    <Button Click="Button_Click" Name="MediaButton">
        <DynamicResource ResourceKey="Play"/>
    </Button>
</Grid>

Now, when the button is clicked, you can simply change the button's content to a different resource (the stop icon). In the button's event handler, you can do this:

C#

private void Button_Click(object sender, RoutedEventArgs e)
{
    if (MediaButton.Content == FindResource("Play"))
    {
        MediaButton.Content = FindResource("Stop");
    }
    else
    {
        MediaButton.Content = FindResource("Play");
    }
}

Edit: Shorter notation

MediaButton.Content = FindResource(MediaButton.Content == FindResource("Play") ? "Stop" : "Play");

Hope this helps, let me know if you have any more questions.

Upvotes: 42

Joee
Joee

Reputation: 2016

Try this code

window.Icon = BitmapFrame.Create(Application.GetResourceStream(new Uri("LiveJewel.png", UriKind.RelativeOrAbsolute)).Stream);

Upvotes: 0

Jan
Jan

Reputation: 693

Use a DataTrigger (edit) in the Image's Style (/edit) on the change condition:

<Button Height="69" HorizontalAlignment="Left" Margin="-2,0,0,0" Name="toggleBroadcast" VerticalAlignment="Top" Width="64" Grid.Row="1" Opacity="0.5" Click="changeBroadcastState_Click">
    <Image>
        <Image.Style>        
            <Style TargetType="{x:Type Image}">
                <Setter Property="Source" Value="Images\playIcon.png" />
                <Style.Triggers>
                    <DataTrigger Binding="{Binding myCondition}" Value="True">
                        <Setter Property="Source" Value="Images\stopIcon.png" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Image.Style>        
    </Image>
</Button>

The myCondition variable would then be a boolean property in your ViewModel (or, more general, the Control's DataContext), something like

public bool myCondition { get { return ([whatever that condition might be]); } }

This may also include a setter and could as well be a simple auto property. As with the other MVVM answer, it will rely on the ViewModel to implement INotifyPropertyChanged.

The nice thing is, once the condition is no longer fulfilled, the DataTrigger will automatically set the Source property back to its original value.

Disclaimer: I have no way to test that right now, so take this with a grain of salt and probably some debugging effort...

Upvotes: 6

ChrisF
ChrisF

Reputation: 137108

If you have your image definition something like this:

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

Then in your code where you want to do the switch simply have:

ImageSource = image;

where image is defined as:

image = new BitmapImage(new Uri("/Application;component/Resources/pause.png", UriKind.Relative));

Of course it does rely on you using the MVVM pattern and implementing the INotifyPropertyChanged interface in your code.

Upvotes: 8

Related Questions