赞
踩
第一种:code_behind中调用Close方法
很明显这个处理并不是很好
第二种:使用behavior
如果是简单的关闭窗口,这样还是ok的
- <Button Content="_">
- <i:Interaction.Triggers>
- <i:EventTrigger EventName="Click">
- <i:ChangePropertyAction TargetObject="{Binding RelativeSource={RelativeSource AncestorType=Window}}" PropertyName="WindowState" Value="{x:Static WindowState.Minimized}"/>
- </i:EventTrigger>
- </i:Interaction.Triggers>
- </Button>
- <Button Margin="5 0" Content="[ ]">
- <i:Interaction.Triggers>
- <i:EventTrigger EventName="Click">
- <i:ChangePropertyAction TargetObject="{Binding RelativeSource={RelativeSource AncestorType=Window}}" PropertyName="WindowState" Value="{x:Static WindowState.Maximized}"/>
- </i:EventTrigger>
- </i:Interaction.Triggers>
- </Button>
- <Button Content="X" Background="LightCoral">
- <i:Interaction.Triggers>
- <i:EventTrigger EventName="Click">
- <!--用上这个可以在关闭前调用VM中的SaveData方法(普通方法就行)-->
- <i:CallMethodAction TargetObject="{Binding}" MethodName="SaveData"/>
- <i:CallMethodAction TargetObject="{Binding RelativeSource={RelativeSource AncestorType=Window}}" MethodName="Close"/>
- </i:EventTrigger>
- </i:Interaction.Triggers>
- </Button>
-- 通过反射,跑到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传过去
<Button Command="CloseCommand" CommandParameter="{Binding RelativeReSource={RelateiveResource AncestorType=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<CloseWindowMessage>(this, (_, m) =>
- {
- this.Close();
- });
第三步:调用(样例是VM中Command调用)
WeakReferenceMessenger.Default.Send(new CloseWindowMessage());
++ 拓展:
可以往CloseWindowMessage中添加属性public object? Sender { get; set; },方便判断这个消息是谁注册的
注册:
- WeakReferenceMessenger.Default.Register<CloseWindowMessage>(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<CloseWindowMessage>(this, (_, m) =>
- {
- if (m.Sender?.Target == this.DataContext)
- this.Close();
- });
发送消息:
WeakReferenceMessenger.Default.Send(new CloseWindowMessage { Sender = new WeakReference(this)});
-----------甚至可以反过来-------------------------------
VM构造方法中注册
WeakReferenceMessenger.Default.Register<RequestMessage<bool>>(this, (object _, RequestMessage<bool> m) => m.Reply(SaveData()));
--SaveData方法的返回值是bool
在按钮的Click事件中调用
- private void Button_Click(object sender, RoutedEventArgs e)
- {
- var response = WeakReferenceMessenger.Default.Send(new RequestMessage<bool>());
- if (response.Response)
- this.Close();
- }
学麻了,要多练习才能记得住
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。