按下 Enter 键时如何关闭 WPF 窗口(对话框)?

Posted

技术标签:

【中文标题】按下 Enter 键时如何关闭 WPF 窗口(对话框)?【英文标题】:How to close WPF window (dialog box) when Enter key is pressed? 【发布时间】:2011-11-22 12:43:46 【问题描述】:

我有一个 WPF window,它作为模式对话框打开。

在对话框中,我有 OKCancel 按钮,它们的 IsDefaultIsCancel 属性分别设置为 True。这两个按钮都有Click 关闭对话框的事件处理程序。

这里是相关的 XAML:

<StackPanel Orientation="Horizontal" Grid.Row="1"  Height="45" VerticalAlignment="Bottom" HorizontalAlignment="Right" Width="190">
    <Button Content="OK"
                Height="25" Margin="10,10,10,10" Width="75" Name="btnOK" TabIndex="1600" IsDefault="True" Click="btnOK_Click"                       
                VerticalContentAlignment="Center" HorizontalContentAlignment="Center" />
    <Button Content="Cancel"
                Height="25" Margin="10,10,10,10" Width="75" Name="btnCancel" TabIndex="1700" IsCancel="True"
                VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Click="btnCancel_Click" />
</StackPanel>

下面是代码:

private void btnOK_Click(object sender, RoutedEventArgs e)

    // My some business logic is here                
    this.Close();


private void btnCancel_Click(object sender, RoutedEventArgs e)

    this.Close();

当我按下键盘上的Esc 按钮时(即使焦点不在Cancel 按钮上),对话框也会按预期关闭。但是,当我在焦点不在OK 按钮上时按Enter 键时,什么也没有发生。

我在对话框中有一个DataGrid。当我选择数据网格中的任何行并按 Enter 时,我想关闭对话框。

如何做到这一点?

一些附加信息:我在对话框上有一个文本框。它具有Keyboard.PreviewKeyDown 事件的事件处理程序。当我在文本框中并按 Enter 键时,不应关闭对话框。 但我可以删除这个处理程序。重要的是解决上述问题。

private void tbxSearchString_PreviewKeyDown(object sender, KeyEventArgs e)

    if (e.Key == Key.Enter)
    
        this.Search(); // Does some searching
    

【问题讨论】:

你遇到的是默认和预期的行为,你不应该改变它。此外,您处理对话的方式有点异国情调。通常,您应该只在按钮的事件处理程序中将DialogResult 设置为truefalse,并且应该在打开对话框的代码中完成逻辑,如下所示:if ((bool)diag.ShowDialog()) /*Here*/ 。跨度> +1 导致 H.B.太快了... :) +1 指出正确的编码方式 (DialogResult)! :) 【参考方案1】:

您的代码对我来说运行良好。当我按下回车键时它关闭对话框。你可以写 e.Handled = true;在 tbxSearchString_PreviewKeyDown 事件中搜索功能之后的行。所以它不会关闭对话框。

<Grid>
        <TextBox Name="tbxSearchString" HorizontalAlignment="Left" Width="100" Height="30" Grid.Row="0" PreviewKeyDown="tt_PreviewKeyDown"></TextBox>
        <StackPanel Orientation="Horizontal" Grid.Row="1"  Height="45" VerticalAlignment="Bottom" HorizontalAlignment="Right" Width="190">

            <Button Content="OK" 
                Height="25" Margin="10,10,10,10" Width="75" Name="btnOK" TabIndex="1600" IsDefault="True" Click="btnOK_Click"                        
                VerticalContentAlignment="Center" HorizontalContentAlignment="Center" />
            <Button Content="Cancel" 
                Height="25" Margin="10,10,10,10" Width="75" Name="btnCancel" TabIndex="1700" IsCancel="True" 
                VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Click="btnCancel_Click" />
        </StackPanel>
    </Grid>

后面的代码

private void btnOK_Click(object sender, RoutedEventArgs e)
        
            DialogResult = true; 
        

        private void btnCancel_Click(object sender, RoutedEventArgs e)
        
            this.Close();
        

        private void tbxSearchString_PreviewKeyDown(object sender, KeyEventArgs e)
        
           if (e.Key == Key.Enter)
           
               this.Search();
               e.Handled = true;
           
        

【讨论】:

+1 表示e.Handled = true。但是,当您设置 DisalogResult 属性时,this.Close() 不是必需的。 感谢 e.Handled = true - 在我的场景中,窗口用返回键关闭,事件冒泡到重新打开窗口的父窗口...;)【参考方案2】:

在 wpf 中没有内置的方法可以关闭对话框窗口。您需要做的是为您的默认按钮设置 DialogResult。所以你只需要以下内容:

xaml

<Button Content="OK" 
            Height="25" Margin="10,10,10,10" Width="75" Name="btnOK" TabIndex="1600" IsDefault="True" Click="btnOK_Click"                        
            VerticalContentAlignment="Center" HorizontalContentAlignment="Center" />

代码隐藏:

    private void btnOK_Click(object sender, RoutedEventArgs e)
    
        DialogResult = true;
    

【讨论】:

问题不在于关闭(Close() 也实现了这一点,即使它不应该在对话框中使用),而是 DataGrid 上的焦点阻止了按钮被按下输入。【参考方案3】:

您不应该自己打电话给Close() 或处理PreviewKeyDown

正确的做法是使用确定/取消按钮,并使用Button.IsDefaultButton.IsCancelWindow.DialogResult。如果在您的文本框中未处理“输入”按下,则按键将传播到Window,并且将按下默认按钮。


MyForm.xaml:

<Button x:Name="btnOk" Content="Ok" Click="btnOk_Click" IsDefault="True"/>
<Button x:Name="btnCancel" Content="Cancel" Click="btnCancel_Click" IsCancel="True"/>

MyForm.xaml.cs:

private void btnOk_Click(object sender, RoutedEventArgs e)

    DialogResult = true;


private void btnCancel_Click(object sender, RoutedEventArgs e)

    DialogResult = false;

现在在表单中的 any 文本框上按 enter 或 escape 将关闭表单(显示正确的结果)

【讨论】:

当用户按 Enter 键时,TextBox 不会在默认模式下更新文本绑定。可以使用 UpdateSourceTrigger=PropertyChanged 确保在 Enter-Key 处理之前更新绑定。【参考方案4】:

只需将 AcceptButton 成员设置为按钮属性名称即可。

AcceptButton = btnOK;   // button used when ENTER is pressed

【讨论】:

AcceptButton 仅适用于 WinForms。

以上是关于按下 Enter 键时如何关闭 WPF 窗口(对话框)?的主要内容,如果未能解决你的问题,请参考以下文章

当我按 Enter 键时,选项卡控件的选项卡页会关闭

如何防止在Enter和Escape键上关闭MFC对话框?

Swing:按下 ESC 键时如何关闭对话框?

键盘 Enter 键在 MFC 对话框中不起作用?

如何在按键盘中的“输入”键时将焦点移到按钮上

在WPF DataGrid中按Enter键时将焦点移动到下一个单元格?