WPF: WpfWindowToolkit 一个窗口操作库的介绍

在 XAML 应用的开发过程中,使用MVVM 框架能够极大地提高软件的可测试性、可维护性。MVVM的核心思想是关注点分离,使得业务逻辑从 View 中分离出来到 ViewModel 以及 Model 中,从逻辑上来讲,这也是业务逻辑应该处的位置。

具体来说,借助于数据绑定 (Data Binding) 以及命令 (Command) 等这些XAML 平台自身所提供的机制,使得 MVVM 在 XAML 平台上很容易实现。但是,如果你对 XAML 应用开发以及 MVVM 的使用有一定的经验,你会发现,单纯 MVVM 本身并不能解决所有问题,比如页面导航、弹出对话框、窗口操作等,这时就需要结合一些与它相关的技术,如消息、行为、服务以及依赖注入等。这个原因是 MVVM 主要针对的是 View 的内容,而不是 View 本身的操作或其它别的东西,所以像弹出窗口或者页面导航之类的操作就需要上述技术的配合。

更具体一点,在 WPF 应用的开发过程中,很多时候我们需要打开和关闭窗口。要以“MVVM方式”来实现,就不容易。当然,我们可以使用消息来解决这个问题。不过,如果过多地使用消息,也会使代码难以维护并且增加调试的难度。

本文主要通过分享一个类库来解决这一问题:WpfWindowToolkit,就如名称所示,它是针对窗口的一些操作类的集合。

一、基本介绍

从介绍里,我们可以看出,它可以解决窗口的打开与关闭,以及在窗口间传递参数和返回值等类的问题,而实现这一切都不需要我们在 View 的 CodeBehind 中写任何代码,也不需要借助于消息,所需要作的修改仅在 XAML 代码和 ViewModel 中,从而遵循了 MVVM 的原则并达到了其目的。

从 Github 下载到源码后,其中有 Demo,通过这个 Demo 我们可以了解它是如何使用的。在以下的内容里,我们先简单对它有些了解,更为具体的内容则可以看它的源码和 Demo。

二、安装

要在项目中使用它,可以从 Nuget 上下载,或者直接使用命令:

InstallPackage WpfWindowToolkit

三、如何使用

1. 打开窗口

有两种方式:使用附加属性或行为。

在使用时,需要先添加命名空间:

    xmlns:behaviors="clr-namespace:PraiseHim.Rejoice.WpfWindowToolkit.Behaviors;assembly=WpfWindowToolkit"
    xmlns:helpers="clr-namespace:PraiseHim.Rejoice.WpfWindowToolkit.Helpers;assembly=WpfWindowToolk

附加属性:

    <Button x:Name="btn1"
        helpers:WindowHelper.OpenWindowType="{x:Type local:Window1}"
        Content="Open window using Window Helper" />

行为:

    <Button x:Name="btn5"
        Margin="0,5,0,0"
        Content="Open window with parameter using action">
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="Click">
                 <behaviors:OpenWindowAction Parameter="WPF (action)" WindowType="{x:Type local:Window1}" />
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </Button>

可以看出,它们都是通过将要打开的窗口的类型(Type) 指定给 WindowType 属性。

2. 打开窗口时传递参数

要在打开窗口的同时,向其 ViewModel 传递参数,也很简单。同上面一样,只需要再为 Parameter 属性赋值即可,这个 Parameter 可以绑定到当前窗口的 ViewModel 的成员上,因此,可以将任何类型的数据传递给要打开的窗口。

接下来,则是需要注意的,要对被打开的窗口的 ViewModel 作一些修改:使它继承 ViewModelBaseData<T>,这里的 T 就是所传递参数的类型。然后,通过 InternalData 属性即可得到传递过来的参数。

    <behaviors:OpenWindowAction Parameter="WPF (action)" WindowType="{x:Type local:Window1}" />
    public class Window1ViewModel : ViewModelBaseData<string>
    {
        protected override string InternalData { get; set; }
        ...
    }

在打开窗口时,还有一种复杂的方式,同时也会给使用者更灵活的控制。方法是,当前窗口继承 ViewModelBaseEx 类,然后调用它的 ShowWindow 方法。在此,再不详述,具体可以参考 Github 上的说明文档。

3. 从被打开的窗口中返回值

当关闭打开的窗口,要实现这个目的,也需要两步,首先,第一个窗口(要打开其它窗口的那个窗口)的 ViewModel 需要继承 ViewModelBaseEx,或 ViewModelBaseEx<T> 类,然后使用 ShowWindow(OpenWindowInfo, Action<TReturnValue>) 方法来打开窗口,其中第二个参数是一个带参数的 Action,这里的参数就是返回值,在这个 Action 中,我们就可以处理返回值 。

    public class ReturnValueMainWindowViewModel : ViewModelBaseEx<Friend>
    {
        public void ShowFriendSelectionWindow()
        {
            this.ShowWindow(new OpenWindowInfo { WindowType = typeof(ReturnValueTestWindow) }, friend =>
            {
                if (friend != null)
                {
                    MessageBox.Show($"You have selected this friend: {friend.Name}");
                }
                else
                {
                    MessageBox.Show("No friend has been selected");
                }
            });
        }
    }

第二步,被打开的窗口的 ViewModel,需要实现 IWindowReturnValue<T> 接口,这个接口包含 ReturnValue 属性,我们只要为它赋值就可以了。

    public class ReturnValueTestWindowViewModel : BindableBase, IWindowReturnValue<Friend>
    {
        ...
        public void SetReturnValue()
        {
            ReturnValue = SelectedFriend;
        }
        ...
    }

4. 关闭窗口

在 View 中关闭

要关闭窗口,可以使用 CloseWindowAction,如下:

    <Button Content="Close the current window with confirmation">
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="Click">
                <behaviors:CloseWindowAction ClosingCheckFunc="{Binding CheckBeforeCloseWindow}" />
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </Button>

它提供一个属性 ClosingCheckFunc,可以绑定到一个返回布尔值的函数,如果此函数返回 true,则关闭,否则,则不关闭。

处理 Window.Closing 事件

除此以外,在窗口被关闭时,它也提供对 Window 的 Closing 事件的支持,通常我们可能会在这个事件处理中来询问是否关闭窗口。要这么做,只要为当前窗口添加一个行为即可,如下:

    <i:Interaction.Behaviors>
        <behaviors:ClosingWindowBehavior ClosingCheckFunc="{Binding CheckBeforeCloseWindow}" />
    </i:Interaction.Behaviors>

而其中的 ClosingCheckFunc 属性所指向的方法则是我们在 ViewModel 中添加的判断逻辑。

在 ViewModel 中关闭窗口

此外,它也支持在 ViewModel 的中来关闭当前窗口,首先,为窗口添加行为:

    <Window>
        <i:Interaction.Behaviors>
            <behavior:EnableWindowCloseBehavior />
        </i:Interaction.Behaviors>
    ...
    </Window>

然后,ViewModel 需要实现 IClosable 接口,它包含一个 Action,名为CloseAction 并在合适的位置调用 CloseAction 即可。

    public class CloseTestViewModel : BindableBase, IClosable
    {
        public Action CloseWindow { get; set; }
        ...
    }
   CloseWindow?.Invoke();  // or just CloseWindow();

总结

本文主要介绍了 WPF 窗口操作库——WpfWindowToolkit 的使用,它完全支持 MVVM,能够解决窗口的打开、关闭、窗口间的传值与返回值等问题。如果你正在开发 WPF 应用,并且采用了 MVVM 模式,不妨试一个这个库。要想多了解,可以到 Github 上下载其源码。

如果什么问题或建议,欢迎随时交流。

原文地址:https://www.cnblogs.com/wpinfo/p/WpfWindowToolkit_Intro.html

时间: 2024-12-10 02:07:58

WPF: WpfWindowToolkit 一个窗口操作库的介绍的相关文章

Cookie 详解以及实现一个 cookie 操作库

Cookie 详解以及实现一个 cookie 操作库 cookie 在前端有着大量的应用,但有时我们对它还是一知半解.下面来看看它的一些具体的用法 Set-Cookie 服务器通过设置响应头来设置客户端的 cookie,形如: Set-Cookie: <cookie名>=<cookie值> 可以同时添加多个 Set-Cookie,从而设置多个 cookie 的值. Set-Cookie 有几个可选项: Expires/Max-Age Expires/Max-Age 可以设置过期时间

[Selenium]通过Selenium实现在当前浏览器窗口点击一个图标之后,弹出另外一个窗口,关闭这个窗口,再回到原来的窗口进行操作

public void clickReportIcon(){ String initialWindowHandle = driver.getWindowHandle(); //保存原始的浏览器窗口 page.getReportIcon().click(); //这个操作之后将会弹出另外一个浏览器窗口 Set <String> set = driver.getWindowHandles(); set.remove(initialWindowHandle); assert set.size()==

IOTutility 一个轻量级的 IOT 基础操作库

目录 IOTutility 一个轻量级的 IOT 基础操作库 1. 为什么要写一个 IOT 编程库? 2. IOTutility 具有什么功能? 3. IOTutility 有什么特点 IOTutility 实现了哪些功能 MQTT protocol implement MQTT 实现 1. 创建一个 MQTT_Session 2. 连接到服务器 3. 订阅感兴趣的主题 4. 可以通过 Publish 接口直接上传消息给服务器 如何使用 1. 下载代码 2. 编译代码库 3. 编译示例程序并执行

WPF实现只打开一个窗口,并且重复打开时已经打开的窗口置顶

内容来自:https://codereview.stackexchange.com/questions/20871/single-instance-wpf-application 第一步:添加System.RunTime.Remoting引用 第二步:新建一个类class1.cs(按自己想法命名) using System; using System.Collections; using System.Collections.Generic; using System.ComponentMode

跨平台网络通信与服务器编程框架库(acl库)介绍

一.描述 acl 工程是一个跨平台(支持LINUX,WIN32,Solaris,MacOS,FreeBSD)的网络通信库及服务器编程框架,同时提供更多的实用功能库.通过该库,用户可以非常容易地编写支持多种模式(多线程.多进程.非阻塞.触发器.UDP方式)的服务器程序,WEB 应用程序,数据库应用程序.此外,该库还提供了常见应用的客户端通信库(如:HTTP.SMTP.ICMP.memcache.beanstalk),常见流式编解码库:XML/JSON/MIME/BASE64/UUCODE/QPCO

Python常用的库简单介绍一下

Python常用的库简单介绍一下fuzzywuzzy ,字符串模糊匹配. esmre ,正则表达式的加速器. colorama 主要用来给文本添加各种颜色,并且非常简单易用. Prettytable 主要用于在终端或浏览器端构建格式化的输出. difflib ,[Python]标准库,计算文本差异 . Levenshtein ,快速计算字符串相似度. Chardet 字符编码探测器,可以自动检测文本.网页.xml的编码. shortuuid ,一组简洁URL/UUID函数库. ftfy ,Uni

window.open()方法用于子窗口数据回调至父窗口,即子窗口操作父窗口

window.open()方法用于子窗口数据回调至父窗口,即子窗口操作父窗口 项目中经常遇到一个业务逻辑:在A窗口中打开B窗口,在B窗口中操作完以后关闭B窗口,同时自动刷新A窗口(或局部更新A窗口)(或将数据传回A窗口) 以下是从实际项目中截取出来和window.open()方法相关的代码,业务逻辑如下: 1. 点击父窗口的div标签(id="addMatchSchedule"),出发点击事件,打开子窗口: 2. 点击子窗口的button按钮,触发点击时间,即调用addSchduleI

进击的Python【第十二章】:mysql介绍与简单操作,sqlachemy介绍与简单应用

进击的Python[第十二章]:mysql介绍与简单操作,sqlachemy介绍与简单应用 一.数据库介绍 什么是数据库? 数据库(Database)是按照数据结构来组织.存储和管理数据的仓库,每个数据库都有一个或多个不同的API用于创建,访问,管理,搜索和复制所保存的数据.我们也可以将数据存储在文件中,但是在文件中读写数据速度相对较慢.所以,现在我们使用关系型数据库管理系统(RDBMS)来存储和管理的大数据量.所谓的关系型数据库,是建立在关系模型基础上的数据库,借助于集合代数等数学概念和方法来

2014 年10个最佳的PHP图像操作库

2014 年10个最佳的PHP图像操作库 Thomas Boutell 以及众多的开发者创造了以GD图形库闻名的一个图形软件库,用于动态的图形计算. GD提供了对于诸如C, Perl, Python, PHP, OCaml等等诸多编程语言的支持. 除了生成HTML输出之外, 你还可以使用php以众多的像 PNG, JPEG, GIF, WBMP,以及 XPM这样的图形文件格式来创建和计算图形文件. 并且,php的使用还能让你可以直接向一个浏览器输出图像流. 为了做到这一点,你需要借助于GD库图像