简体   繁体   English

使用ShowDialog和无边框窗口时,IsMouseOver触发器不起作用

[英]IsMouseOver trigger doesn't work when using ShowDialog and borderless window

I have two Windows for an application. 我有两个Windows用于应用程序。 One of them is MainWindow and the other is for settings. 其中一个是MainWindow ,另一个是设置。 SettingsWindow opens when settings button is clicked by using ShowDialog and setting its Owner to MainWindow . 使用ShowDialog单击设置按钮并将其Owner设置为MainWindow时,将打开SettingsWindow

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 . SettingsWindow我在窗口的最底部有一个按钮,它在IsMouseOverTrue时将颜色更改为红色 ,为False时将颜色更改为蓝色 But it doesn't change when the cursor is over the MainWindow. 但是当光标在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. CASE:光标不在SettingsWindow中,但它保持红色,没有变化。

在此输入图像描述

Xaml code: 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>

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. 基本上,我们可以使用Show()并添加一些代码来更接近模态行为 - 比如禁用父窗口,直到对话框关闭或用户选择了OK或取消为例。

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: 订阅了settingsWindow关闭事件后,我们现在可以在settingsWindow关闭时再次启用父窗口:

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 . 为此,您可以使用Peheje 在此处发布的代码。

I used this to program a working example. 我用它来编写一个工作示例。 While leaving your window, the Button gets the correct style. 离开窗口时,Button会获得正确的样式。

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 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. 这适用于我:在设置Window.Resources下定义样式资源(用于按钮) - 然后此样式设置新模板(边框),默认背景为蓝色,IsMouseOver触发器将其更改为红色。 Reference the style either explicitly for implicitly (both worked for me). 隐式地明确引用样式(两者都适用于我)。

Link to small test project: https://1drv.ms/u/s!AhlMAmchX3R6nDJ1MXS6DxlRXtnA 链接到小型测试项目: 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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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