Триггер IsMouseOver не работает при использовании ShowDialog и окна без полей
У меня два Windows
для приложения. Один из них является MainWindow
а другой для настроек. SettingsWindow
открывается при нажатии кнопки настроек с помощью ShowDialog
и установив его Owner
в MainWindow
,
На SettingsWindow
У меня есть кнопка в самом низу окна, и она меняет цвет на красный, когда IsMouseOver
является True
и синий для False
, Но это не меняется, когда курсор находится над MainWindow. Изображение ниже, чтобы быть ясным. Как я могу исправить эту проблему?
CASE: курсор находится вне SettingsWindow, но сохраняет красный цвет, без изменений.
XAML код:
<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>
3 ответа
Хорошо, после некоторого исследования я не смог найти никакой логической причины для этого. Это больше похоже на ошибку для меня. Так что, если кто-то точно знает, почему это происходит, дайте нам знать!
Во всяком случае, я нашел обходной путь. По сути, мы можем использовать Show() и добавить некоторый код, чтобы приблизиться к модальному поведению - например, отключить родительское окно, пока диалоговое окно не закроется или пользователь не выберет, например, OK или Отмена.
Пример:
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
После подписки на закрытое событие settingsWindow теперь мы можем снова включить родительское окно, когда закрывается settingsWindow:
private void onWindowClosed(object sender, EventArgs e)
{
this.IsEnabled = true;
}
Триггеры теперь будут работать правильно, и родительское окно будет отключено, пока его дочерний элемент не будет закрыт.
Я думаю, что вы должны наблюдать за положением мыши вручную. Для этого вы можете использовать код, размещенный Peheje здесь.
Я использовал это для программирования рабочего примера. При выходе из окна, кнопка получает правильный стиль.
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>
Это работает для меня: Определите ресурс стиля (для кнопки) в настройках Window.Resources - Этот стиль затем устанавливает новый шаблон (границу), фон по умолчанию как синий и триггер IsMouseOver, чтобы изменить его на красный. Ссылка на стиль либо явно для неявно (оба работали для меня).
Ссылка на небольшой тестовый проект: 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>