简体   繁体   中英

C# WPF MVVM trigger change background color of button permanently

I want to change the color of my button permanently, if the user clicked a button. How do I achieve that in XAML? The trigger I have right now won't work, because they are only temporary, not overriding default values.

Here my button template:

<Style TargetType="{x:Type Button}" x:Key="ButtonStyleNavigation">
            <Setter Property="Background" Value="Transparent" />
            <Setter Property="Foreground" Value="#FF365B74" /> 
            <Setter Property="IsTabStop" Value="False"/>
            <Setter Property="FontFamily" Value="Arial" />
            <!-- <Setter Property="BorderThickness" Value="2"/>-->
            <!-- <Setter Property="BorderBrush" Value="Yellow"/>-->

            <Setter Property="FontSize" Value="15" />

            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">
                        <Border CornerRadius="10" Background="{TemplateBinding Background}">
                            <Grid>
                                <ContentPresenter x:Name="MyContentPresenter" Content="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="5,0,5,0" />
                            </Grid>
                        </Border>

                        <ControlTemplate.Triggers>

                            <Trigger Property="IsEnabled" Value="false">
                                <Setter Property="Opacity" Value="0.3"/>
                            </Trigger>

                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter Property="Foreground" Value="Yellow" />
                                <Setter Property="Background" Value="#FF658EAA"/>
                            </Trigger>

                            <Trigger Property="IsPressed" Value="True">
                                <Setter Property="Background" Value="Yellow" />
                                <Setter Property="Foreground" Value="#FF658EAA" />
                            </Trigger>

                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

SOLUTION:

So, I was able to get what I needed with the use of a ToggleButton . I've bound for each button one property to their IsChecked function. In my ViewModel I change the checked-state accordingly to my desire. (mentioned in the comments)

Here is my new ToggleButton template:

<Style TargetType="{x:Type ToggleButton}" x:Key="ButtonStyleNavigation">
            <Setter Property="Background" Value="Transparent" />
            <Setter Property="Foreground" Value="#FF365B74" />
            <Setter Property="IsTabStop" Value="False"/>
            <Setter Property="FontFamily" Value="Arial" />

            <Setter Property="FontSize" Value="15" />

            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ToggleButton}">
                        <Border CornerRadius="10" Background="{TemplateBinding Background}" Height="19">
                            <Grid>
                                <ContentPresenter x:Name="MyContentPresenter" Content="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="5,0,5,0" />
                            </Grid>
                        </Border>

                        <ControlTemplate.Triggers>
                            <Trigger Property="IsChecked" Value="True">
                                <Setter Property="Foreground" Value="Yellow" />
                                <Setter Property="Background" Value="#FF658EAA"/>
                            </Trigger>

                            <Trigger Property="IsChecked" Value="False">
                                <Setter Property="Background" Value="Transparent" />
                                <Setter Property="Foreground" Value="#FF365B74" />
                            </Trigger>

                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter Property="Foreground" Value="Yellow" />
                                <Setter Property="Background" Value="#FF658EAA"/>
                            </Trigger>

                            <Trigger Property="IsPressed" Value="True">
                                <Setter Property="Background" Value="Yellow" />
                                <Setter Property="Foreground" Value="#FF658EAA" />
                            </Trigger>

                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

Sounds like you want a ToggleButton. They have a bool property called "IsChecked" that changes each time you click the button.

Taking the style you provided and changing it like so should achieve what you want.

<Style TargetType="{x:Type ToggleButton}" x:Key="ButtonStyleNavigation">
            <Setter Property="Background" Value="Transparent" />
            <Setter Property="Foreground" Value="#FF365B74" />
            <Setter Property="IsTabStop" Value="False"/>
            <Setter Property="FontFamily" Value="Arial" />

            <Setter Property="FontSize" Value="15" />

            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ToggleButton}">
                        <Border CornerRadius="10" Background="{TemplateBinding Background}">
                            <Grid>
                                <ContentPresenter x:Name="MyContentPresenter" Content="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="5,0,5,0" />
                            </Grid>
                        </Border>

                        <ControlTemplate.Triggers>

                            <Trigger Property="IsEnabled" Value="false">
                                <Setter Property="Opacity" Value="0.3"/>
                            </Trigger>

                            <Trigger Property="IsChecked" Value="True">
                                <Setter Property="Background" Value="Yellow" />
                                <Setter Property="Foreground" Value="#FF658EAA" />
                            </Trigger>

                            <Trigger Property="IsChecked" Value="False">
                                <Setter Property="Background" Value="Transparent" />
                                <Setter Property="Foreground" Value="#FF658EAA" />
                            </Trigger>

                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

I have removed the IsMouseOver trigger as it conflicts with the IsChecked triggers.

When you say you permanently i presume this is what you mean. If you wish for the button to remain the same colour after a user clicks on the button again, you will have to deal with click events and check for number of clicks on the button.

EDIT:

As per your comment, if you want to have only one button enabled at time, look into using radio buttons instead.

Here is a tutorial on getting multiple radio buttons set up.

Check out this answer on how to style them to look like normal buttons.

You can then use the triggers in a similar fashion to check for enum values in your view model.

Here is a pure xaml answer, using a ControlTemplate as requested, taking your original question and just changing the <ControlTemplate.Triggers> section:

<ControlTemplate.Triggers>
    <EventTrigger RoutedEvent="Button.Click">
        <BeginStoryboard>
            <Storyboard>
                <ColorAnimation Storyboard.TargetProperty="(Button.Foreground).(SolidColorBrush.Color)" To="Yellow" Duration="0"/>
                <ColorAnimation Storyboard.TargetProperty="(Button.Background).(SolidColorBrush.Color)" To="#FF658EAA" Duration="0"/>
            </Storyboard>
        </BeginStoryboard>
    </EventTrigger>
</ControlTemplate.Triggers>

In your original question you had (perhaps unintentionally) triggered from the mouse over event, in which case change here the RoutedEvent accordingly.

NB. You may be able to find an alternative to ColourAnimation with a zero duration, but I thought I'd post this as it at least gives you something to work with.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM