无法在WPF中设置DialogResult

30
我使用ShowDialog()从调用窗口显示一个WPF窗口。窗口按预期打开并且是模态的。但是,在对话框窗口中,在我的OK和Cancel按钮的单击事件中,我分别设置了this.DialogResult = true (或false),但是该值未被设置。窗口按预期关闭,但是DialogResult仍然为空。
这是WPF中的错误吗?或是因为DialogResult属性不能被设置而不会抛出异常?该窗口不托管在浏览器中。
调用窗口中的代码:
Window2 win = new Window2();
bool? result = win.ShowDialog();
if (result.HasValue && result.Value) {
   //never gets here because result is always null
}

对话框中的代码:

this.DialogResult = true;

你如何将 DialogResult 设置为布尔值?它应该是一个枚举,比如 DialogResult.OK。 - Brandon
13
在WPF中,如果你使用ShowDialog()方法打开一个Window对象,你可以将DialogResult设置为布尔值。 - Carlo
你能在这里发布你的<Window ... />定义内容吗?也许这与你初始化窗口的方式有关。 - Drew Noakes
1
那个Window2是什么? 你是从Window派生出自己的Window类吗? 那么问题可能出在你的Window2类上,你应该发布它的源代码。 - Simon D.
我刚遇到了这个问题,似乎是从自己的窗口类派生时出现了一个错误。不确定如何解决它。 - craftworkgames
10个回答

18

DialogResult 是一个可空的布尔类型。不过,你不必强制转换就可以获取它的值。

bool? result = myWindow.ShowDialog();
if (result ?? false)
{
  // snip
}

如果结果为空,?? 将设置默认值返回。更多信息请查看: 可空类型使用(C# 编程指南)

至于原始问题,我只在设置 DialogResult 和关闭窗口之间处理窗口时遇到并跟踪了此问题。不幸的是,我唯一能提供的建议就是逐步检查您的代码并检查操作的顺序。我相信通过设置 DialogResult 然后明确地关闭窗口来“修复”它。


窗口此时未被释放。 - quinnapi
没错。我的一个朋友使用 result.Value 来获取 true 或 false。 - Junior Mayhé
4
我更喜欢使用 result == true,因为这样更易读。如果使用 ?? 的话,我会需要思考它在这里的含义。 - svick
3
“result == true”是我非常反感的一个习惯。因为“== true”是隐式的。如果你想让代码更易读,建议为变量取代表它们含义的名字。 例如:bool? isOK = myWindow.Dialog(); if (isOK ?? false) { ... } - MetaFight
8
使用 bool? 时,== true 永远不是隐式的。 - Riegardt Steyn

10

首先,你必须考虑到它返回的是一个可空的布尔值(bool?),因此为了比较或将其设置为另一个变量,你必须将其强制转换为常规布尔型

bool result = (bool)myWindow.DialogResult;

关于它为空的问题...我不明白为什么会发生这种情况,除非在被设置为true或false之后又被重新设置为空。你能展示一下你的代码吗?

编辑:

你的代码对我来说已经可以正常工作了,这是我在第二个窗口中的代码:

private void button2_Click(object sender, RoutedEventArgs e)
{
    this.DialogResult = false;
}

private void button1_Click(object sender, RoutedEventArgs e)
{
    this.DialogResult = true;
}

而在Window1中:

private void window1_Loaded(object sender, RoutedEventArgs e)
{
    Window2 win = new Window2();

    bool? result = win.ShowDialog();

    if (result.HasValue && result.Value)
    {
        //it DID get here
    }
}

有什么大的区别吗?


3
在调试会话中,我在将 DialogResult 设置为 true 后立即检查其值,但它仍然为 null。 - quinnapi
没有区别。事实上,我在同一项目中使用几个其他窗口也是完全相同的操作,它们都可以正常工作。 - quinnapi
尝试在 win.ShowDialog() 之后使用 bool? result = win.DialogResult;...我知道这并不可靠,但让我们试试。您认为我需要获取哪些其他信息来重新创建场景?这是一些奇怪的行为... - Carlo
5
@quinnapi 哈哈,两年后,我遇到了同样的问题。我刚刚意识到我在读自己的答案。真烦人! - Carlo
@Carlo - 请看一下https://dev59.com/83I-5IYBdhLWcg3wn526#1759505,这里有一种非常优雅的方法,可以用一个简单的附加属性来替换那些代码后台事件处理程序。 - David Keaveny

8

我刚刚遇到了完全相同的问题,似乎是由于我覆盖了OnClosing()方法造成的。我需要覆盖OnClosing()来阻止用户通过关闭(X)按钮关闭模态窗口。

当我注释掉OnClosing()方法时,问题就消失了,并且DialogResult返回了预期的true或false值。

出于兴趣,这是我的按钮单击处理程序和OnClosing方法:

private void AlternateButton_Click(object sender, RoutedEventArgs e)
{
    this.DialogResult = false;
    buttonHasBeenClicked = true;
    this.Close();
}

private void DefaultButton_Click(object sender, RoutedEventArgs e)
{
    this.DialogResult = true;
    buttonHasBeenClicked = true;
    this.Close();
}

protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
    base.OnClosing(e);
    if (!buttonHasBeenClicked)
    {
        // Prevent the user closing the window without pressing one of the buttons.
        e.Cancel = true;
    }
}

作为对此的跟进,我刚刚从窗口中删除了关闭(x)按钮,因此我不再需要覆盖OnClosing()。更多信息请参见:https://dev59.com/z3RB5IYBdhLWcg3wCjYV - dodgy_coder
即使关闭(x)按钮被隐藏,用户仍然可以通过按下Alt-F4或单击其“IsCancel”属性设置为“True”的按钮来关闭窗口。 - Ed Noepel
我曾经遇到过类似的问题。你的帖子帮了我很多!谢谢! - al2suarez
我曾经遇到过同样的问题,多亏了@dodgy_coder,我找到了问题的根源。DialogResult的setter调用了Close链接。你的OnClosing事件处理程序设置了e.Cancel,这显然会重置DialogResult。解决方法是先设置buttonHasBeenClicked(以防止取消关闭),然后再设置DialogResult - Jiří Skála

4

我也遇到过这个问题,我找到的唯一解决方法是在我的类中使用以下代码:

public new bool? DialogResult { get; set; }

在设置了我的DialogResult之后,它对我有用了!(非常奇怪的问题)。 这是我使用的代码:

cmdCancel = new RelayCommand(() => { DataContact.Reload(); this.DialogResult = false; this.Close(); });

并且要打开我的对话框:

public static MessageBoxResult ShowQuestionYesNo(string message)
        {
            POLMessageBox w = new POLMessageBox("سوال", MessageBoxType.QuestionYesNo, message);
            w.ShowDialog();
            var b = w.DialogResult;
            if (b == true) return MessageBoxResult.Yes;
            if (b == false) return MessageBoxResult.No;
            return MessageBoxResult.No;
        }

在查看了几个答案之后,我最终也采取了这种方法。它很丑陋,需要文档和注释,但这是避免 WPF 踩到我的脚趾的唯一方法。 - Grault

2

在设置DialogResult之前,你是否关闭了窗口?你应该发布按钮事件处理程序的整个内容。


我认为这是正确的。我们解决这个问题的唯一方法就是看更多的上下文。 - PeterAllenWebb

0

我在对话框窗口页面中有以下内容。(dialogwindow.xaml.cs)

   private void dlgWindowYesButton_Click(object sender, RoutedEventArgs e)
    {
        this.DialogResult = true;
        this.Close();
    }

    private void dlgWindowNoButton_Click(object sender, RoutedEventArgs e)
    {
        this.DialogResult = false;
        this.Close();
    }

在调用页面中,我使用了以下方式的对话框窗口:
dialogwindow dWinObj = new dialogwindow();
if(dWinObj.ShowDialog().Value == true)
{
  //perform the operation when the user clicks "Yes"
}

0

我也遇到了这个问题。原来是我在IF语句的括号内设置了DialogResult,因此(尽管看起来很奇怪)导致了错误。一旦删除了这一行代码,问题就解决了。

private void OKButton_Click(object sender, RoutedEventArgs e)
    {
        if (!string.IsNullOrEmpty(startBlockPosBox.Text))
        {
          .. do stuff ..
        }
        else
        {
          .. do stuff ..
          DialogResult = true; // this line caused the problem
        }

        DialogResult = true;
    }

0
问题出在表单的生命周期上:
对话框事件 private void _loginViewModel_LoginEvent(object sender, LoginViewModel.LoginEventArgs e) { DialogResult = true; this.Close(); }
正常工作:
var login = new Login();
var result = login.ShowDialog();

不起作用:

var result = new Login().ShowDialog();

0
我通过在这个语句之后加上this.close(),并添加this.DialogResult=truewindow.ShowDialog(),返回true的方式解决了这个问题。
private void Button1_Click(object sender, RoutedEventArgs e)
{
    this.Close();
    this.DialogResult = true;
}

-1
我曾经遇到过类似的问题,但我的问题是由于在我的关闭语句中的代码引起的。我试图在窗口关闭之前Dispose()一个List,然后将List<>属性设置为null...当我尝试将其值设置为null时,它卡住了set属性,因此我想出了以下笨拙的解决方法,在我的set属性方法中一切都正常工作:
    List<SettingItem> settingItems;
    public IEnumerable<SettingItem> Settings
    {
        get
        {
            return settingItems.OrderBy(t => t.Name).AsEnumerable();
        }
        set
        {
            if (value == null)
            {
                settingItems.Clear();
            }
            else
            {
                settingItems = value.ToList();
            }
        }
    }

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