第一种:code_behind中调用Close方法
很明显这个处理并不是很好
第二种:使用behavior
如果是简单的关闭窗口,这样还是ok的
-- 通过反射,跑到Window中调用Close方法,或者修改WindowState
中间那颗按钮想要实现再点击一次实现窗口正常大小就有点复杂
并且如果需要在关闭窗口前保存好数据的方法SaveData是有返回参数的,这样就不是很好了
第三种:委托绑定关闭窗口,普通Command
在VM中设置关闭窗口的委托,可以是Action;通过Command进行激活,可以在激活之前调用DataSave对数据进行保存。
View中绑好这个Command,code_behind中将VM中的Action绑定上this.Close()方法
第四种:将Window传给VM
参考:WPF传递任意控件或任意控件的属性给ViewModel_wpf绑定viewmodel的方法 并且传递一个name指定的控件实例-CSDN博客
显然如果直接将整个Window传给VM中的Command那肯定是不太好的,这个时候可以借助接口传过去。
第一步:将Window传过去
第二步:创建带有关闭窗口的接口
public interface ICloseWindow
{
void CloseWindow();
}
第三步:让View的code_behind接上这个接口并实现方法,方法的内容就是调用Close()方法关闭窗口
第四步:对应的VM中的Command
[RelayCommand]
void Close(ICloseWindow window)
{
if (SaveData()) // 保存数据相关的方法
{
CloseWindow?.Invoke();
}
}
使用MvvmToolKit中的WeakReferenceMessenger
第一步:首先注册一个类,这里是CloseWindowMessage,这个类什么都不用动,作用应该仅仅是标记同一个消息,方便调用
第二步:被调用(样例是code_behind中的关闭)
WeakReferenceMessenger.Default.Register(this, (_, m) =>
{
this.Close();
});
第三步:调用(样例是VM中Command调用)
WeakReferenceMessenger.Default.Send(new CloseWindowMessage());
++ 拓展:
可以往CloseWindowMessage中添加属性public object? Sender { get; set; },方便判断这个消息是谁注册的
注册:
WeakReferenceMessenger.Default.Register(this, (_, m) =>
{
if (m.Sender == this.DataContext)
this.Close();
});
发送消息:
WeakReferenceMessenger.Default.Send(new CloseWindowMessage { Sender = this});
++ 再改进:
但是这样又有不好的地方,这个引用印象到GC的释放;因此可以将CloseWindowMessage类中的object属性改为public WeakReference? Sender { get; set; }
然后变成:
注册:
WeakReferenceMessenger.Default.Register(this, (_, m) =>
{
if (m.Sender?.Target == this.DataContext)
this.Close();
});
发送消息:
WeakReferenceMessenger.Default.Send(new CloseWindowMessage { Sender = new WeakReference(this)});
-----------甚至可以反过来-------------------------------
VM构造方法中注册
WeakReferenceMessenger.Default.Register>(this, (object _, RequestMessage m) => m.Reply(SaveData()));
--SaveData方法的返回值是bool
在按钮的Click事件中调用
private void Button_Click(object sender, RoutedEventArgs e)
{
var response = WeakReferenceMessenger.Default.Send(new RequestMessage());
if (response.Response)
this.Close();
}
学麻了,要多练习才能记得住