WinUI 3 ContentDialog自定义对话框结果实现及问题排查
解决方案
1. 修复堆栈溢出问题
你的ShowAsync()方法递归调用了自身,导致堆栈溢出。需要明确调用基类的ShowAsync()方法:
public new Task<ContDialogResult> ShowAsync() { _taskCompletionSource = new(); // 调用基类的ShowAsync,而非自身的方法 _ = base.ShowAsync(); return _taskCompletionSource.Task; }
2. 替换静态DialogResult为实例字段
静态字段会导致多个对话框实例互相干扰,改成私有实例字段:
// 替换原来的静态字段 private ContDialogResult _dialogResult = ContDialogResult.None;
3. 处理Enter键触发确认逻辑
给密码输入框添加KeyDown事件,捕获Enter键并执行确认逻辑:
在XAML的PasswordBox中添加事件:
<PasswordBox x:Name="AdminPasswordBox" KeyDown="AdminPasswordBox_KeyDown"/>
然后在代码后台实现事件处理:
private void AdminPasswordBox_KeyDown(object sender, KeyRoutedEventArgs e) { if (e.Key == Windows.System.VirtualKey.Enter) { Ok_Click(sender, e); e.Handled = true; } }
4. 调整Closed事件与按钮逻辑
更新按钮点击事件和Closed事件,使用实例字段_dialogResult:
private void ContentDialog_Closed(ContentDialog sender, ContentDialogClosedEventArgs e) { _taskCompletionSource?.SetResult(_dialogResult); // 重置状态,避免复用实例时出错 _dialogResult = ContDialogResult.None; this.IncorrectPinTextBlock.Visibility = Visibility.Collapsed; } private void Ok_Click(object sender, RoutedEventArgs e) { if (this.AdminPasswordBox.Password == ConfigurationManager.AppSettings["AdminPassword"].ToString()) { _dialogResult = ContDialogResult.OK; this.Hide(); } else { this.IncorrectPinTextBlock.Visibility = Visibility.Visible; } } private void Cancel_Click(object sender, RoutedEventArgs e) { _dialogResult = ContDialogResult.Cancel; this.Hide(); }
完整修复后的代码
public sealed partial class PasswordDia : ContentDialog { private TaskCompletionSource<ContDialogResult>? _taskCompletionSource; private ContDialogResult _dialogResult = ContDialogResult.None; public enum ContDialogResult { None, Cancel, OK, } public PasswordDia() { this.InitializeComponent(); this.IncorrectPinTextBlock.Visibility = Visibility.Collapsed; this.Closed += ContentDialog_Closed; } private void ContentDialog_Closed(ContentDialog sender, ContentDialogClosedEventArgs e) { _taskCompletionSource?.SetResult(_dialogResult); _dialogResult = ContDialogResult.None; this.IncorrectPinTextBlock.Visibility = Visibility.Collapsed; } public new Task<ContDialogResult> ShowAsync() { _taskCompletionSource = new(); _ = base.ShowAsync(); return _taskCompletionSource.Task; } private void Ok_Click(object sender, RoutedEventArgs e) { if (this.AdminPasswordBox.Password == ConfigurationManager.AppSettings["AdminPassword"].ToString()) { _dialogResult = ContDialogResult.OK; this.Hide(); } else { this.IncorrectPinTextBlock.Visibility = Visibility.Visible; } } private void Cancel_Click(object sender, RoutedEventArgs e) { _dialogResult = ContDialogResult.Cancel; this.Hide(); } private void AdminPasswordBox_KeyDown(object sender, KeyRoutedEventArgs e) { if (e.Key == Windows.System.VirtualKey.Enter) { Ok_Click(sender, e); e.Handled = true; } } }
使用方式
调用对话框时,直接等待自定义的ShowAsync()结果:
var dialog = new PasswordDia(); var result = await dialog.ShowAsync(); if (result == PasswordDia.ContDialogResult.OK) { // 处理确认逻辑 } else if (result == PasswordDia.ContDialogResult.Cancel) { // 处理取消逻辑 }
内容的提问来源于stack exchange,提问作者E. A. Bagby
相关产品推荐
相关产品推荐

