Триггер 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>
Другие вопросы по тегам