Home > OS >  Why am I not able to use IsMouseOver property in WPF more than 1 time?
Why am I not able to use IsMouseOver property in WPF more than 1 time?

Time:10-10

<Window x:Class="KrakenZ_Tweaker.MainWindow"
    ResizeMode="CanMinimize"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:KrakenZ_Tweaker"
    mc:Ignorable="d"
    Title="KrakenZ Tweaker" Height="700" Width="1000" >
<Grid Background="#FF4E4E4E" Margin="0,0,0,0" >


    <StackPanel HorizontalAlignment="Left" Background="#FF121820" Height="700" Width="300">
        <Image  HorizontalAlignment="Center" Margin="0,30,0,12" Height="125" Width="140" Source="/KrakenZ-Tweaker-Logo.ico"/>
        <TextBlock Margin="0,0,0,9" TextWrapping="Wrap" Text="  KrakenZ Tweaker" FontFamily="Montserrat" FontSize="30" Foreground="White" Height="34" Width="257"/>
        <Separator Width="187" Height="8" Background="Gray"/>
        <Button x:Name="Restore_Point" Margin="10" Height="47" Width="279" BorderBrush="{x:Null}" Foreground="White" FontFamily="Bahnschrift" FontSize="25" Content="Restore Point" Cursor="Hand" Click="Restore_Point_Click">
            <Button.Style>
                <Style TargetType="{x:Type Button}">
                    <Setter Property="Background" Value="#175EBD"/>
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type Button}">
                                <Border Background="{TemplateBinding Background}">
                                    <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
                                </Border>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                    <Style.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="Background" Value="DarkGoldenrod"/>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </Button.Style>
            <Button.Resources>
                <Style TargetType="Border">
                    <Setter Property="CornerRadius" Value="8"/>
                </Style>
            </Button.Resources>
        </Button>
        <Button x:Name="Disable_Unnecessary_Services" Margin="10" Height="47" Width="279" BorderBrush="{x:Null}" Foreground="White" FontFamily="Bahnschrift" FontSize="25" Content="Disable Services" Cursor="Hand" Click="Disable_Unnecessary_Services_Click">
            <Button.Style>
                <Style TargetType="{x:Type Button}">
                    <Setter Property="Background" Value="#121820"/>
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type Button}">
                                <Border Background="{TemplateBinding Background}">
                                    <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
                                </Border>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                    <Style.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="Background" Value="DarkGoldenrod"/>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </Button.Style>
            <Button.Resources>
                <Style TargetType="Border">
                    <Setter Property="CornerRadius" Value="8"/>
                </Style>
            </Button.Resources>
        </Button>
        <Button x:Name="Clear_Junk_Files" Margin="10" Height="47" BorderBrush="#121820" Width="279" Foreground="White" FontFamily="Bahnschrift" FontSize="25" Content="Clear Junk Files" Cursor="Hand" Click="Clear_Junk_Files_Click">
            <Button.Style>
                <Style TargetType="{x:Type Button}">
                    <Setter Property="Background" Value="#121820"/>
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type Button}">
                                <Border Background="{TemplateBinding Background}">
                                    <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
                                </Border>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                    <Style.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="Background" Value="DarkGoldenrod"/>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </Button.Style>
            <Button.Resources>
                <Style TargetType="Border">
                    <Setter Property="CornerRadius" Value="8"/>
                </Style>
            </Button.Resources>
        </Button>
        <Button x:Name="Useful_Optimization" Margin="10" Height="47" Width="279" BorderBrush="{x:Null}" Foreground="White" FontFamily="Bahnschrift" FontSize="25" Content="Useful Optimizations" Cursor="Hand" Click="Useful_Optimization_Click">
            <Button.Style>
                <Style TargetType="{x:Type Button}">
                    <Setter Property="Background" Value="#121820"/>
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type Button}">
                                <Border Background="{TemplateBinding Background}">
                                    <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
                                </Border>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                    <Style.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="Background" Value="DarkGoldenrod"/>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </Button.Style>
            <Button.Resources>
                <Style TargetType="Border">
                    <Setter Property="CornerRadius" Value="8"/>
                </Style>
            </Button.Resources>
        </Button>

    </StackPanel>
    <StackPanel x:Name="User_Control" Margin="308,2,6,0"/>







</Grid>
This is my MainWindow.XAML code.
 private void Restore_Point_Click(object sender, RoutedEventArgs e)
    {
        Restore_Point.Background = (Brush)(new BrushConverter().ConvertFrom("#175EBD"));
        Disable_Unnecessary_Services.Background = (Brush)(new BrushConverter().ConvertFrom("#121820"));
        Clear_Junk_Files.Background = (Brush)(new BrushConverter().ConvertFrom("#121820"));
        Useful_Optimization.Background = (Brush)(new BrushConverter().ConvertFrom("#121820"));
        User_Control.Children.Remove(UC2);
        User_Control.Children.Remove(UC3);
        User_Control.Children.Remove(UC4);
        User_Control.Children.Add(defaultUC);
       
       

    }

    private void Disable_Unnecessary_Services_Click(object sender, RoutedEventArgs e)
    {
       Disable_Unnecessary_Services.Background = (Brush)(new BrushConverter().ConvertFrom("#175EBD"));
        Restore_Point.Background = (Brush)(new BrushConverter().ConvertFrom("#121820"));
        Clear_Junk_Files.Background = (Brush)(new BrushConverter().ConvertFrom("#121820"));
        Useful_Optimization.Background = (Brush)(new BrushConverter().ConvertFrom("#121820"));
        User_Control.Children.Remove(defaultUC);
        User_Control.Children.Remove(UC3);
        User_Control.Children.Remove(UC4);
        User_Control.Children.Add(UC2);


    }

    private void Clear_Junk_Files_Click(object sender, RoutedEventArgs e)
    {
        Clear_Junk_Files.Background = (Brush)(new BrushConverter().ConvertFrom("#175EBD"));
        Disable_Unnecessary_Services.Background = (Brush)(new BrushConverter().ConvertFrom("#121820"));
        Restore_Point.Background = (Brush)(new BrushConverter().ConvertFrom("#121820"));
        Useful_Optimization.Background = (Brush)(new BrushConverter().ConvertFrom("#121820"));
        User_Control.Children.Remove(defaultUC);
        User_Control.Children.Remove(UC2);
        User_Control.Children.Remove(UC4);

        User_Control.Children.Add(UC3);
    }

    private void Useful_Optimization_Click(object sender, RoutedEventArgs e)
    {
        Useful_Optimization.Background = (Brush)(new BrushConverter().ConvertFrom("#175EBD"));
        Clear_Junk_Files.Background = (Brush)(new BrushConverter().ConvertFrom("#121820"));
        Disable_Unnecessary_Services.Background = (Brush)(new BrushConverter().ConvertFrom("#121820"));
        Restore_Point.Background = (Brush)(new BrushConverter().ConvertFrom("#121820"));
        User_Control.Children.Remove(defaultUC);
        User_Control.Children.Remove(UC2);
        User_Control.Children.Remove(UC3);
        User_Control.Children.Add(UC4);

    }

These are the event handlers for all the buttons. The problem happening with me here is that I am able to use the IsMouseOver property only once. After I click any button, I am not able to use this property. I think this problem is due to the event handers of the buttons click but I am not sure of this. Pls help in this. Thanks in advance.

CodePudding user response:

By setting the Control.Background property explicitly/locally you override/remove the style triggers. This behavior is desired and is implemented by following the common WPF value precedence rules for dependency properties. Additionally, your code contains a lot of duplicate code, which you should always avoid.

To persist such control specific (visual) behavior you must not define the corresponding triggers in a Style, but in the ControlTemplate.

If like in your case the Button has a "is clicked" toggle state, you usually would prefer a ToggleButton (or in your case even a RadioButton).
This would enable you to handle the clicked state more convenient via triggers alone.
This will help you to understand your code much better, as visual effects can now be implemented in one place (instead of spreading it across multiple styles and code-behind).

For this reason, you should generally avoid defining multiple styles for a control (like you did), if those styles are not global or defined locally: defining two Style resources using the Button.Style and the Button.Resources property makes your code hard to read. Better move appearance related configuration directly to the corresponding template elements (because you are already overriding the ControlTemplate).

And because all templates are essentially the same, you can easily avoid duplicate code by extracting them to a ResourceDictionary within a common scope (for example Window.Resources).

Your fixed and improved code could look as follows:

<Window>
  <Window.Resources>
    <Style x:Key="RadioButtonStyle" 
           TargetType="RadioButton">
      <Setter Property="Background"
              Value="#121820" />
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate TargetType="{x:Type RadioButton}">
            <Border x:Name="Border"
                    CornerRadius="8"
                    Background="{TemplateBinding Background}">
              <ContentPresenter HorizontalAlignment="Center"
                                VerticalAlignment="Center" />
            </Border>

            <!-- 
              Note that the order of the triggers is important. 
              To allow the IsMouseOver trigger to have a higher priority than the IsChecked trigger, 
              the IsMouseOver trigger must be defined after the IsChecked trigger. 
              Trigger priority is interpreted low to high from top to down 
            -->
            <ControlTemplate.Triggers>
              <Trigger Property="IsChecked"
                       Value="True">
                <Setter TargetName="Border"
                        Property="Background"
                        Value="#175EBD" />
              </Trigger>
              <Trigger Property="IsMouseOver"
                       Value="True">
                <Setter TargetName="Border"
                        Property="Background"
                        Value="DarkGoldenrod" />
              </Trigger>
            </ControlTemplate.Triggers>
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>
  </Window.Resources>

  <StackPanel>
    <RadioButton x:Name="Restore_Point"
                 Style="{StaticResource RadioButtonStyle}"
                 Margin="10"
                 Height="47"
                 Width="279"
                 BorderBrush="{x:Null}"
                 Foreground="White"
                 FontFamily="Bahnschrift"
                 FontSize="25"
                 Content="Restore Point"
                 Cursor="Hand"
                 Click="Restore_Point_Click" />
    <RadioButton x:Name="Disable_Unnecessary_Services"
                 Style="{StaticResource RadioButtonStyle}"
                 Margin="10"
                 Height="47"
                 Width="279"
                 BorderBrush="{x:Null}"
                 Foreground="White"
                 FontFamily="Bahnschrift"
                 FontSize="25"
                 Content="Restore Point"
                 Cursor="Hand"
                 Click="Disable_Unnecessary_Services_Click" />
    <RadioButton x:Name="Clear_Junk_Files"
                 Style="{StaticResource RadioButtonStyle}"
                 Margin="10"
                 Height="47"
                 Width="279"
                 BorderBrush="{x:Null}"
                 Foreground="White"
                 FontFamily="Bahnschrift"
                 FontSize="25"
                 Content="Restore Point"
                 Cursor="Hand"
                 Click="Clear_Junk_Files_Click" />
  </StackPanel>
</Window>

Since the background of the buttons is now completely handled in XAML, you now can cleanup the event handlers.
Now the Button.Click event handlers will look as follows:

private void Restore_Point_Click(object sender, RoutedEventArgs e)
{
  User_Control.Children.Remove(UC2);
  User_Control.Children.Remove(UC3);
  User_Control.Children.Remove(UC4);
  User_Control.Children.Add(defaultUC);
}

private void Disable_Unnecessary_Services_Click(object sender, RoutedEventArgs e)
{
  User_Control.Children.Remove(defaultUC);
  User_Control.Children.Remove(UC3);
  User_Control.Children.Remove(UC4);
  User_Control.Children.Add(UC2);
}

private void Clear_Junk_Files_Click(object sender, RoutedEventArgs e)
{
  User_Control.Children.Remove(defaultUC);
  User_Control.Children.Remove(UC2);
  User_Control.Children.Remove(UC4);
  User_Control.Children.Add(UC3);
}
  • Related