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

12

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

在对话框上,我有一个 OK 和一个 Cancel 按钮,它们的 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
    }
}

3
你遇到的是默认和预期的行为,不应该更改它。此外,你处理对话框的方式有点奇特;通常你只需要在按钮的事件处理程序中将 DialogResult 设置为 truefalse,并且逻辑应该在打开对话框的代码块中完成,像这样:if ((bool)diag.ShowDialog()) { /*Here*/ } - H.B.
+1 是因为 H.B. 太快了... :) - blindmeis
+1 指出正确的编码方式(DialogResult)! :) - Learner
4个回答

10

你的代码对我来说运行良好。当我按下回车键时,它会关闭对话框。在tbxSearchString_PreviewKeyDown事件中,在搜索功能后面编写e.Handled = true;行。这样它就不会关闭对话框了。

<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;
           }
        }

3
+1 意味着 e.Handled = true。但是,在设置 DialogResult 属性时,不必使用 this.Close() - Learner
1
感谢 e.Handled = true - 在我的情况下,窗口通过回车键关闭,并且事件冒泡到父窗口,重新打开了窗口... ;) - Lumo

8

在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" />

codebehind:

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

问题不在于关闭对话框(Close()也可以实现,尽管不应该在对话框中使用),而在于 DataGrid 上的焦点阻止了按 Enter 键时按钮的响应。 - H.B.

8

您不应该自己调用Close()或处理PreviewKeyDown

正确的做法是使用确定/取消按钮,并使用Button.IsDefaultButton.IsCancelWindow.DialogResult。如果在文本框中未处理“enter”按键,则按键将传播到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;
}

现在,在表单中按下回车或ESC键将关闭表单(并返回正确的结果),这适用于表单中的任何文本框。

当用户按下回车键时,TextBox在默认模式下不会更新文本绑定。可以使用“UpdateSourceTrigger=PropertyChanged”来确保在处理回车键之前更新绑定。 - Dennis Kuypers

0
只需将 AcceptButton 成员设置为按钮属性名称即可。
AcceptButton = btnOK;   // button used when ENTER is pressed

2
AcceptButton仅适用于WinForms。 - AntonK

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接