I have two Windows
for an application. One of them is MainWindow
and the other is for settings. SettingsWindow
opens when settings button is clicked by using ShowDialog
and setting its Owner
to MainWindow
.
On the SettingsWindow
I have a button at the very bottom of the window and it changes the color to red when IsMouseOver
is True
and blue for False
. But it doesn't change when the cursor is over the MainWindow. The image is below to be clear. How can I fix this problem?
CASE: The cursor is out of SettingsWindow but it keeps the red color, no change.
Xaml code:
<Window x:Class="AltoSS.SettingsWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="SettingsWindow"
Height="150"
Width="360"
WindowStyle="None"
AllowsTransparency="True"
WindowStartupLocation="CenterOwner">
<!-- Other control codes-->
<Button Grid.Row="2" Content="KAYDET"
FontSize="15"
FontWeight="Bold"
BorderBrush="Gray"
BorderThickness="0,2,0,2">
<Button.Style>
<Style TargetType="Button">
<Setter Property="Background" Value="Blue"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Red"/>
<Setter Property="Foreground" Value="White"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Button.Style>
</Button>
</Window>
Alright, after doing some research, I couldn't find any logical reason for this to occur. It seems more like a bug to me. So if anyone knows exactly why this happens, let us know!
Anyway, I've come up with a workaround. Basically, we can use Show() and add some code to get closer to a modal behavior - like disabling the parent window until the dialog gets closed or the user has selected OK or Cancel for instance.
Example:
SettingsWindow settingsWindow = new SettingsWindow();
this.IsEnabled = false; //disables the main window
settingsWindow.Owner = this; // main window is the settings window owner
settingsWindow.Show();
settingsWindow.Closed += (o, e1) => { onWindowClosed(o,e1); }; // this is the close event
After subscribing for the settingsWindow closed event, we can now enable the parent window again when settingsWindow gets closed:
private void onWindowClosed(object sender, EventArgs e)
{
this.IsEnabled = true;
}
Triggers will now work correctly and parent window gets disabled until its child is closed.
I think you have to observe the mouse position manually. For this you could use the code behind posted by Peheje here.
I used this to program a working example. While leaving your window, the Button gets the correct style.
using System.Runtime.InteropServices;
using Point = System.Drawing.Point;
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetCursorPos(ref Point lpPoint);
public bool IsMouseOverButton {
get { return _isMouseOverButton; }
set {
if (value == _isMouseOverButton) return;
_isMouseOverButton = value;
OnPropertyChanged();
}
}
public SettingsWindow()
{
InitializeComponent();
new Thread(() =>
{
while (true)
{
//Logic
Point p = new Point();
GetCursorPos(ref p);
//Update UI
Application.Current.Dispatcher.Invoke(() =>
{
double btnLeft = DlgWindow.Left;
double btnRight = btnLeft + DlgBtn.ActualWidth;
double btnBottom = DlgWindow.Top + DlgWindow.ActualHeight;
double btnTop = btnBottom - DlgBtn.ActualHeight;
IsMouseOverButton =
p.X >= btnLeft && p.X <= btnRight &&
p.Y >= btnTop && p.Y <= btnBottom;
});
//async wait (non blocking)
(new ManualResetEvent(false)).WaitOne(100);
}
}).Start();
}
xaml
<Window x:Name="DlgWindow"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
AllowsTransparency="True">
<Button x:Name="DlgBtn"
Height="50"
VerticalAlignment="Bottom"
BorderBrush="Gray"
BorderThickness="0,2,0,2"
Content="KAYDET"
FontSize="15"
FontWeight="Bold">
<Button.Style>
<Style TargetType="Button">
<Setter Property="Background" Value="Blue"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding IsMouseOverButton}" Value="True">
<Setter Property="Background" Value="Red" />
<Setter Property="Foreground" Value="White" />
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Button.Style>
</Button>
This works for me: Define a style resource (for the button) under settings Window.Resources - This style then sets the new Template (a border), the default background as blue, and the IsMouseOver trigger to change it to red. Reference the style either explicitly for implicitly (both worked for me).
Link to small test project: https://1drv.ms/u/s!AhlMAmchX3R6nDJ1MXS6DxlRXtnA
<Window x:Class="IsMouseOverTriggerSecondWindow.SettingsWindow"
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:IsMouseOverTriggerSecondWindow"
mc:Ignorable="d"
Title="SettingsWindow" Height="170" Width="330">
<!-- my settings window button style-->
<!-- defined as a resource in SettingsWindow.xaml, so it doesnt effect MainWindow -->
<Window.Resources>
<Style TargetType="Button" >
<Setter Property="Background" Value="Blue"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}">
<ContentPresenter Content="{TemplateBinding Content}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<TextBlock Text="This is the settings window" />
<Button Content="KAYDET" Height="30" VerticalAlignment="Bottom" Foreground="White" FontWeight="Bold" />
</Grid>
</Window>