WPF(MVVM):closuresViewmodel的视图?
任何人碰到使用MVVM在视图模型中closures视图的巧妙方法?
也许有一种使用绑定的方式来指示视图(窗口)closures?
我真的很感激任何人有任何input。
基本上我有一个loginView绑定到一个loginViewModel,在viewmodel(使用一个命令绑定)我testing,看看如果login是成功的,如果是我基本上加载一个新的视图(主视图),并附加其datacontext。 ..
但我仍然有loginView显示 – 所以我需要信号它卸载..
我也希望有一个通用的解决scheme,因为我相信在其他情况下我需要做这种事情
有任何想法吗?
编辑:看我的博客文章更详细的解释。
当我需要实现这一点时,我使用我创build的IRequestCloseViewModel接口。
该接口只包含一个事件:RequestClose。 这个事件是由ViewModel(它inheritance自一个ViewModelBase类和实现IRequestCloseViewModel)当它想要closures它的相关视图引发的。
在我的应用程序中,所有Window都从一个抽象类ApplicationWindowinheritance。 每当DataContext发生变化时,都会通知此抽象类,并在处理程序中检查DataContext是否支持IRequestCloseViewModel。 如果是这种情况,事件处理程序被设置为当事件被触发时closures窗口。
或者像肯特所说的那样,你可以使用屏幕控制器来处理这个外部类的机制。
不知道你正在使用什么MVVM框架,但大多数包含某种消息/通知解决scheme,很容易注册发送的消息的东西。 没有任何理由可以想象你的视图不能注册诸如“CloseWindowsBoundTo”之类的消息,并且视图模型作为发送者。 然后在你的视图中,你可以注册该消息,并将你当前的datacontext与发送者进行比较。 如果他们匹配,closures窗口。
简单,并保持你的视图从你的视图模型抽象。
这里是我使用MVVM-light工具包的方法:
在ViewModel中:
public void notifyWindowToClose() { Messenger.Default.Send<NotificationMessage>( new NotificationMessage(this, "CloseWindowsBoundToMe") ); }
而在视图中:
Messenger.Default.Register<NotificationMessage>(this, (nm) => { if (nm.Notification == "CloseWindowsBoundToMe") { if (nm.Sender == this.DataContext) this.Close(); } });
一般情况下,您可以使用某种控制器/演示者/服务来驱动屏幕激活/停用。 MVVM并不意味着成为统治它们的一种模式 。 您将需要在任何非平凡的应用程序中将其与其他模式相结合。
也就是说,在某些情况下,有一个pipe理子视图模型生命周期的视图模型是有意义的。 例如,您可能有一个EditorViewModel
来pipe理子视图模型的集合 – 每个正在编辑的文档都有一个。 在这种情况下,简单地添加/删除/从这个集合可以导致视图激活/停用。 但是这听起来不像你的用例。
http://adammills.wordpress.com/2009/07/01/window-close-from-xaml/
<Style.Triggers> <DataTrigger Binding="{Binding CloseSignal}" Value="true"> <Setter Property="Behaviours:WindowCloseBehaviour.Close" Value="true" /> </DataTrigger> </Style>
我知道这是一个古老的问题,但我有一个很好的方式,所以我想我会分享给其他人绊倒这一点。 我曾经使用dialogcloser附加的行为,但我发现下面的解决scheme,我可以使用它更容易。 为简单起见,下面的示例为窗口上的closuresbutton示例。
通过窗口作为命令参数。
在buttonxaml中查看:
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"
在视图模型中的命令execute方法中:
if (parameter is System.Windows.Window) { (parameter as System.Windows.Window).Close(); }
您可以创build一个附加到窗口的命令,并在执行时closures该窗口。 然后,可以将该命令绑定到视图模型上的属性,并在要closures窗口时执行该命令。
我会使用一个ApplicationController实例化LoginViewModel并显示LoginView。 当用户进入login屏幕时,ApplicationControllerclosuresLoginView并显示MainViewModel的MainView。
WPF应用程序框架(WAF)项目的示例应用程序中显示了如何完成此任务。
这个答案显示了另一种方式来做到这一点
ViewModel应该如何closures表单?
它使用附加属性将DialogResult窗口属性绑定到ViewModel属性。 当将DialogResult的值设置为true或false时,视图被closures。
只需在后台代码中的EventHandler中closures,并在视图模型中处理其他任何可以使用命令绑定的地方。
要closuresviewmodel的视图,我使用了Galasoft MVVM Light Toolkit,你可以从这里下载: http ://www.mvvmlight.net/
-
像这样创build一个类:public class ClosingRequested:MessageBase {}
-
把这个添加到你的视图构造函数:Messenger.Default.Register(this,vm,msg => Close());
-
调用这个来closures你的窗口:Messenger.Default.Send(new ClosingRequested(),this);
你也可以使用事件来做到这一点。 虽然你需要在你的视图代码背后需要3行代码(有些MVVM纯粹主义者不喜欢这样);
在你的viewmodel中,你创build了一个视图可以订阅的事件:
public event CloseEventHandler Closing; public delegate void CloseEventHandler(); private void RaiseClose() { if (Closing != null) Closing(); }
在你的视图中,你可以在你的initializecomponent方法之后订阅这个事件,如下所示:
public View { *//The event can be put in an interface to avoid direct dependence of the view on the viewmodel. So below becomes //ICloseView model = (ICloseView)this.DataContext;* ProgressWindowViewModel model = (ProgressWindowViewModel)this.DataContext; model.Closing += Model_Closing; } private void Model_Closing() { this.Close(); }
当您准备好closuresViewModel中的视图时,只需调用RaiseClose()即可。
您甚至可以使用此方法将消息从视图模型发送到视图。
事件可以放在一个接口中,以避免视图对视图模型的直接依赖。