我一直在查看典型的“从viewmodel提升对话框”问题的视图示例,注意到3个主要解决方案:
我有点陷入困境,并努力找到一个容易融入我的问题空间的解决方案 - 这是一个非常简单的文件复制问题:
我主要在那里,但我遇到的最大困难是: - 如何在等待输入时暂停viewmodel中的循环 - 如何将输入返回到循环内的viewmodel,以便它可以继续
到目前为止,我倾向于服务解决方案,因为它似乎是一个直接的方法调用,返回vm必须等待。但是,它确实意味着服务需要直接绑定到视图以使元素可见?
如果有人可以发布一些直接处理这个问题的简单代码,我(和网)会非常高兴!谢谢!
答案 0 :(得分:0)
例如,您有一个名为IDialogService
的服务,其中包含以下界面:
public interface IDialogService
{
bool ConfirmAction(string title, string confirmationText);
}
正如您所提到的,为了使服务能够显示实际的对话框,它需要引用将显示实际覆盖元素的视图。但是我不想直接引用视图,而是通过接口引用它。让我们称之为ICanShowDialog
,它将拥有以下成员:
public interface ICanShowDialog
{
void ShowDialog(object dialogContent);
void HideDialog();
}
此界面将由拥有对话框叠加层的视图(例如您的主窗口)实现。
现在有趣的部分:在显示对话框时暂停代码执行。首先,我建议你不要使用覆盖元素,但如果可能的话使用常用的窗口。那你就没有那个问题了。您可以设置对话框窗口的样式,使其看起来就像叠加元素一样。 无论如何,如果您仍然想使用overlay元素,那么您可以执行以下技巧来暂停代码执行:
以下是ConfirmAction
inteface的IDialogService
方法的伪代码:
public bool ConfirmAction(string title, string confirmationText)
{
ConfirmationDialogView dialogView = new ConfirmationDialogView(title, confirmationText);
DialogShower.ShowDialog(dialogView); // DialogShower is of type ICanShowDialog
while (!dialogView.ResultAvailable)
{
DispatcherUtils.DoEvents();
}
DialogShower.HideDialog();
return dialogView.Result;
}
以下是DispatcherUtils.DoEvents()
的代码(取自此处:http://dedjo.blogspot.com/2007/08/how-to-doevents-in-wpf.html):
public static class DispatcherUtils
{
public static void DoEvents()
{
DispatcherFrame f = new DispatcherFrame();
Dispatcher.CurrentDispatcher.BeginInvoke(
DispatcherPriority.Background,
(SendOrPostCallback)delegate(object arg) {
DispatcherFrame fr = arg as DispatcherFrame;
fr.Continue=True;
}, f);
Dispatcher.PushFrame(frame);
}
}
但我必须警告你。使用DoEvents
可能会导致内部调度程序循环导致的一些细微错误。
作为在显示对话框时暂停代码执行的替代方法,您可以使用回调:
public interface IDialogService
{
void ConfirmAction(string title, string confirmationText, Action<bool> dialogResultCallback);
}
但使用它不会那么方便。