【问题标题】:WPF Loses Event HandlerWPF 丢失事件处理程序
【发布时间】:2017-12-21 18:14:38
【问题描述】:

我在 .NET 4.7 中有一个简单的 WPF 应用程序。主窗口监听“Key Up”事件。如果按下 Escape 键,主窗口会自行关闭。这工作正常(至少它开始工作正常)。

主窗口还包含一个打开另一个窗口的按钮(称为 X)。 X 只是一个空的窗口。它没有事件处理程序。当 X 打开时,主窗口中的按钮被禁用。一旦 X 关闭,按钮就会重新启用。

问题是:一旦 X 关闭,主窗口的 Key Up 事件处理程序似乎就消失了……有点。我不能再按 Escape 来关闭主窗口除非我首先将焦点放在其中一个按钮上。如果我只是单击主窗口并按 Escape,它不会关闭窗口。在展示 Window X 之前,情况并非如此。

事实证明,如果我禁用并重新启用按钮,则 Key Up 事件处理程序在 X 关闭后继续工作——我仍然可以通过按下来可靠地关闭主窗口退出键。

显然,我是 WPF 的新手。我想知道 Windows 事件是否发生了一些奇怪的事情。

这是主窗口的 XAML,后面是它的代码。我还包含了 Window X 的 XAML 和代码(顺便说一句,Window X 是 WrapPanelWindow)。

<Window x:Class="Wpf_01.MainWindow" x:ClassModifier="internal"
    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:Wpf_01"
    mc:Ignorable="d"
    Title="Main Window" Height="300" Width="300" Background="#FF6289A4" KeyUp="Key_Up">

<StackPanel Margin="20,10,20,10">
    <Button Content="Canvas Example"/>
    <Button Content="WrapPanel Example" Click="Button_Click"/>
    <Button Content="DockPanel Example"/>
    <Button Content="Grid Example"/>
    <Button Content="StackPanel Example"/>
</StackPanel>

下面是主窗口的代码:

namespace Wpf_01 {
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    internal partial class MainWindow : Window {
        public MainWindow() {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e) {
            Button clickedButton = sender as Button;
            Window newWindow = null;

            switch(clickedButton.Content) {
                case "Canvas Example":
                    newWindow = new CanvasWindow();
                    break;
                case "WrapPanel Example":
                    newWindow = new WrapPanelWindow();
                    break;
            }

            if(newWindow != null) {
                clickedButton.IsEnabled = false;

                newWindow.Show();

                newWindow.Closed += (x, y) => clickedButton.IsEnabled = true;
            }
        } // Button_Clicked()


        private void Key_Up(object sender, KeyEventArgs e) {
            if(e.Key == Key.Escape)
                Close();
        } // KeyHandler()
    }
}

这里是 WrapPanelWindow XAML 和后面的代码:

<Window x:Class="Wpf_01.WrapPanelWindow" x:ClassModifier="internal"
        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:Wpf_01"
        mc:Ignorable="d"
        Title="Fun with WrapPanel Window" Height="200" Width="260">
    <Grid>

    </Grid>
</Window>

最后是 WrapPanelWindow 的代码。

namespace Wpf_01 {
    /// <summary>
    /// Interaction logic for WrapPanelWindow.xaml
    /// </summary>
    internal partial class WrapPanelWindow : Window {
        public WrapPanelWindow() {
            InitializeComponent();
        }
    }
}

【问题讨论】:

  • 我刚刚测试了你的代码,它运行良好。我怀疑还有更多代码。如果是这样,请发布它。如果有任何与这些事件相关的 XAML 也会发布。如果我们无法重现,我们将无法回答您的问题
  • 添加的代码看起来不错。确保清理解决方案(在解决方案资源管理器中右键单击解决方案)并重建它。在 Key_Up 方法中设置断点 (F9) 以查看它是否被调用。
  • @Erno - 断点不会被击中。 X 关闭后,我可以将焦点放回其中一个按钮上,Escape 键将关闭主窗口。但如果焦点在主窗口本身,它就不起作用。
  • 几点说明: 1. 在我的机器上,如果窗口有焦点,它确实可以工作。 2. 如果用户打开多个窗口,此设置将不会缩放(一旦关闭退出按钮再次启用) 3. 更好的解决方案是将所有打开的窗口添加到列表中,并且仅在以下情况下关闭窗口/应用程序列表为空。 (不要忘记从列表中删除关闭的窗口)
  • @Erno:奇怪的是它对你有用。就我而言,一旦 Window X 关闭,特定的 Button 需要在 Escape 关闭 Window 之前获得焦点。例如,我不能简单地单击窗口的标题栏并按 Escape。

标签: wpf


【解决方案1】:

当您关闭 CanvasWindow 时,主窗口没有重新获得焦点。当您禁用该按钮时,窗口上的其他任何内容都无法聚焦。

如果您从 Windows 任务栏中选择应用程序(最小化和恢复)或切换程序并使用 Ctrl+Tab 返回它可以工作。

尝试在重新启用 clickedButton 后获得焦点:

            newWindow.Closed += (x, y) =>
            {
                clickedButton.IsEnabled = true;
                clickedButton.Focus();
            };

【讨论】:

  • 窗口可以在我的机器上获得焦点
  • @Edu:WrapPanelWindow 根本没有控件,因此没有“可聚焦”控件。如果您在 WrapPanelWindow 上放置一个 Key Up 处理程序,它将键入关键事件。所以,似乎一个窗口可以拥有焦点。
  • @Tom:Focus 有两种类型。键盘和逻辑。如果窗口返回时没有控件具有键盘焦点,则它不起作用。如果在窗口再次处于活动状态时任何控件具有键盘焦点,则它可以工作。仅在窗口上的逻辑焦点不会捕获键盘输入(请参阅docs.microsoft.com/en-us/dotnet/framework/wpf/advanced/…
  • 我只需单击主窗口(标题栏或可用空间),它就会获得焦点。
  • @Erno:您获得了逻辑焦点,但没有键盘焦点。 (请参阅 docs.microsoft.com/en-us/dotnet/framework/wpf/advanced/...)
猜你喜欢
  • 2017-12-16
  • 1970-01-01
  • 2022-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-18
  • 2014-09-28
  • 1970-01-01
相关资源
最近更新 更多