Cli*_*int 6 c# wpf mvvm reactiveui
我有一个observable,我用它来显示一个确认对话框,大致是签名:
IObservable<DialogResult> ShowDialog(string title, string message);
Run Code Online (Sandbox Code Playgroud)
这向用户显示了对话框,带有是/否按钮组合.
在我的主窗口中,我正在访问结束事件:
this.Events().Closing.[Do something here]
Run Code Online (Sandbox Code Playgroud)
我希望能够:
CancelEventArgs.Cancel如果用户单击"否"按钮,则将该属性设置为true.我试过直接订阅:
this.Events().Closing.Subscribe(e =>
{
var res = Dialogs.ShowDialog("Close?", "Really Close?").Wait();
e.Cancel = res == DialogResult.Ok;
});
Run Code Online (Sandbox Code Playgroud)
但是因为这个Wait()电话而挂起,我也尝试过异步变种:
this.Events().Closing.Subscribe(async e =>
{
var res = await Dialogs.ShowDialog("Close?", "Really Close?");
e.Cancel = res == DialogResult.Ok;
});
Run Code Online (Sandbox Code Playgroud)
哪个不好,因为它马上就会回来.
我真正想要做的是:
this.Events().Closing.ThenDo(_ => Dialogs.ShowDialog("Close?", "Really Close?"))
.Subscribe((cancelEventArgs, dialogResult) =>
{
cancelEventArgs.Cancel == dialogResult == DialogResult.Ok;
});
Run Code Online (Sandbox Code Playgroud)
但这不存在,我知道这里的关键在于我如何组合这两个可观察量,但我不知道如何这样做,而且文档对实际例子有点了解.
您需要阻止 Closing 事件处理程序,因此异步(或 Rx 操作)在这里对您没有多大帮助。
但您还需要以仍然处理 UI 事件的方式阻止它,这样 UI 就不会冻结。
最常见的解决方案是使用 Window.ShowDialog 而不是 Show,以下代码有效:
this.Events().Closing.Subscribe(e =>
{
var ret = new Window().ShowDialog();
e.Cancel = true;
});
Run Code Online (Sandbox Code Playgroud)
但是在 ShowDialog Rx 方法中使用它会使其订阅调用阻塞,而这不太可能是您想要的(对于其他情况,在本例中这就是您所需要的)。
或者,您可以运行内部调度程序循环,如下所示:
this.Events().Closing.Subscribe(e =>
{
var dialog = Dialogs.ShowDialog("Close?", "Really Close?");
var dispatcherFrame = new DispatcherFrame();
dialog.Take(1).Subscribe(res => {
e.Cancel = res == DialogResult.Ok;
dispatcherFrame.Continue = false;
});
// this will process UI events till the above fires
Dispatcher.PushFrame(dispatcherFrame);
});
Run Code Online (Sandbox Code Playgroud)
仅当两个窗口使用相同的调度程序时,这才有效。
编辑:
或者,您可以通过始终取消关闭并稍后自己关闭表单来避免阻塞,这可能更像是 Rx 方式,即:
var forceClose = default(bool);
this.Events().Closing
.Where(_ => !forceClose)
.Do(e => e.Cancel = true)
.SelectMany(_ => Dialogs.ShowDialog("Close?", "Really Close?"))
.Where(res => res == DialogResult.Ok)
.Do(_ => forceClose = true)
.Subscribe(_ => this.Close());
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1040 次 |
| 最近记录: |