MVVM下的窗口关闭

50 篇文章 0 订阅

第一种: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();
}

学麻了,要多练习才能记得住

  • 8
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值