在我的Windows窗体应用程序中,我有一个子窗体,由我的主窗体作为模态启动。子表单充当向导以执行长时间运行的任务,并包含"取消"按钮。在设计师中,我有这个"取消"按钮的DialogResult
属性设置为DialogResult.Cancel
。但是,如果用户拒绝按下"取消"按钮直到长操作完成,"取消"按钮更改为"关闭"。如果发生这种情况,我希望按钮DialogResult
为DialogResult.None
。
不幸的是,设置似乎并不存在。为了维护响应式UI,长时间运行的任务在单独的Task
中运行,然后在任务完成后更新UI,之后在ContinueWith
块中完成,然后使用{{1做UI工作。它看起来像这样:
Invoke
当我运行代码时,文本设置为"关闭",没问题。 Task.Factory.StartNew(() =>
{
MyStaticClass.DoLotsOfWork(a, b, myCancellationToken);
return MyStaticClass.TellMeAboutIt(a, c, myCancellationToken);
}, myCancellationToken)
.ContinueWith(task =>
{
switch(task.Status)
{
case TaskStatus.RanToCompletion:
Invoke((MethodInvoker)delegate
{
cancelButton.Text = "Close";
cancelButton.DialogResult = DialogResult.None;
// other UI-related stuff.
}
// Other cases here...
}
});
似乎要更改:如果我使用调试器,调试器会告诉我值已更改。但是,当窗口关闭时(使用取消/关闭按钮),DialogResult
返回的DialogResult
总是 myWindow.ShowDialog()
。
这是一个错误吗?难道我做错了什么?一个人是否可以在运行中以编程方式设置按钮的DialogResult.Cancel
?
答案 0 :(得分:5)
将DialogResult设置为“取消”的原因不止一个。例如,您可能会在按钮的Click事件处理程序中调用Close()。这会关闭窗口,但由于从未分配过DialogResult,Winforms必须假设取消。隐藏窗口是触发此窗口的另一种方式,当您使窗口不可见时,窗口不能保持模态。必要的是,所有其他窗口都被禁用,最后一个窗口被隐藏,用户再也无法返回该程序。
处理对话状态的理智方法是只设置DialogResult属性。只要将其从None更改为其他内容,Winforms将关闭对话框,对话框结果将明确无误。因此,请考虑删除Click事件处理程序并将代码更改为:
case TaskStatus.RanToCompletion:
Invoke((MethodInvoker)delegate
{
cancelButton.Text = "Close";
cancelButton.DialogResult = DialogResult.OK;
}