You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 09:25:09