信息宝贝 发表于 2023-9-21 17:19:52

循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(6)

在我们窗口新增、编辑状态下的时候,我们往往会根据是否修改过的痕迹-也就是脏数据状态进行跟踪,如果用户发生了数据修改,我们在用户退出窗口的时候,提供用户是否丢弃修改还是继续编辑,这样在一些重要录入时的时候,可以避免用户不小心关掉窗口,导致窗口的数据要重新录入的尴尬场景。本篇随笔介绍基于WPF开发中,窗口控件脏数据状态IsDirty的跟踪处理操作。
 1、WPF的Page页面、Window窗口对象和视图模型

MVVM是Model-View-ViewModel的简写。类似于目前比较流行的MVC、MVP设计模式,主要目的是为了分离视图(View)和模型(Model)的耦合。
对于MVVM应用中,MVVM其中包括Model、View、ViewModel三者内容。其中Page或者Window对象,都是属于视图View的概念。由于目前我们程序框架大多数情况下采用IOC的控制反转方式来调用,因此对象和接口的注入是程序开始的重要工作。
.net 中 负责依赖注入和控制反转的核心组件有两个:IServiceCollection和IServiceProvider。其中,IServiceCollection负责注册,IServiceProvider负责提供实例。在注册接口和类时,IServiceCollection提供了三种注册方法,如下所示:
1、services.AddTransient<IDictDataService, DictDataService>();// 瞬时生命周期
2、services.AddScoped<IDictDataService, DictDataService>();<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings> // 域生命周期
3、services.AddSingleton<IDictDataService, DictDataService>();// 全局单例生命周期如果使用AddTransient方法注册,IServiceProvider每次都会通过GetService方法创建一个新的实例;
如果使用AddScoped方法注册, 在同一个域(Scope)内,IServiceProvider每次都会通过GetService方法调用同一个实例,可以理解为在局部实现了单例模式;
如果使用AddSingleton方法注册, 在整个应用程序生命周期内,IServiceProvider只会创建一个实例。
了解了这几个不同的注入方式,有助于我们了解WPF的整个注入对象的生命周期,对于页面来说,由于采用了导航的方式,我们在注入的时候,采用单例的方式,对于弹出的编辑、新增、导入、批量处理的这种常规视图,我们采用用完就丢弃的AddTransient方式,而视图模型为了方便,我们也采用单件的方式构建即可。
我们在WPF程序入口的程序代码App.xaml.cs中注入相关的对象信息。
登录窗口和主窗口,采用单件注入方式,如下代码所示。
// 程序导航主窗体及视图模型
services.AddSingleton<INavigationWindow, MainWindow>();
services.AddSingleton<ViewModels.MainWindowViewModel>();
//登录窗口
services.AddSingleton<LoginView, LoginView>();而对于我们程序的视图或者视图模型对象来做,我们不可能一一按名字插入,应该通过一种动态的方式来批量处理,也就是根据各自的接口类型/继承基类来处理即可。
#region 加入视图页面和视图模型
//使用动态方式加入
var types = System.Reflection.Assembly.GetExecutingAssembly().DefinedTypes.Select(type => type.AsType());

//视图页面对象 typeof(Page),使用单件模式,每次请求都是一样的页面
var viewPageBaseType = typeof(Page);
var pageClasses = types.Where(x => x != viewPageBaseType && viewPageBaseType.IsAssignableFrom(x))
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>.Where(x => x.IsClass && !x.IsAbstract).ToList();
foreach (var page in pageClasses)
{
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>services.AddSingleton(page);
}

//视图模型对象 typeof(ObservableObject)
var viewModelBaseType = typeof(ObservableObject);
var viewModels = types.Where(x => x != viewModelBaseType && viewModelBaseType.IsAssignableFrom(x))
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>.Where(x => x.IsClass && !x.IsAbstract).ToList();
foreach (var view in viewModels)
{
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>services.AddSingleton(view);
}

//窗口对象,使用 Transient 模式,每次请求都是一个新的窗体
var windowBaseType = typeof(Window);
var windowClasses = types.Where(x => x != windowBaseType && windowBaseType.IsAssignableFrom(x))
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>.Where(x => x.IsClass && !x.IsAbstract).ToList();
foreach (var window in windowClasses)
{
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>services.AddTransient(window);
}
#endregion以上就是普通列表页面Page类型、视图模型ViewModel、弹出式窗口的几种注入的方式,通过接口判断和基类判断的方式,自动注入相关的对象。
2、对窗口控件的修改进行跟踪

了解了上面几种对象的注入方式,我们来进一步了解弹出式窗口对象Window的控件的修改状态跟踪。
由于WPF不能像Winform那种,通过父对象的Controls集合就可以遍历出来所有的对象,然后进行一一判断,而WPF对象没有这个属性,因此也就无法直接的对控件的修改状态进行跟踪。
那是不是没有办法对窗口下面的控件进行一一判断了呢?肯定不是,办法还是有的,就是通过内置辅助类LogicalTreeHelper,或者VisualTreeHelper的方式,由于前者是所有窗口或者页面的逻辑控件都会跟踪到,后者VisualTreeHelper只是对可视化的控件进行跟踪,因此我们这里选择LogicalTreeHelper来对控件进行遍历处理。
实现的效果,就是对应窗口编辑内容发生变化,如果用户退出,提示用户即可,如下界面效果所示。

 由于窗口元素都是继承自Visual这个wpf的基类,而这个基类又是继承于DependencyObject,如下代码所示。
public abstract class Visual : DependencyObject而辅助类,可以通过GetChildren的方法获取对应的控件列表,接口如下所示。
IEnumerable GetChildren(DependencyObject current)稍微封装下对控件的递归遍历处理,代码如下所示。
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>/// <summary>
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>/// 使用辅助类对窗口控件进行遍历处理
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>/// </summary>
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>/// <typeparam name="T">控件类型</typeparam>
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>/// <param name="depObj">父对象</param>
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>/// <returns></returns>
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>public static IEnumerable<T> <strong>FindLogicalChildren</strong><T>(DependencyObject depObj) where T : DependencyObject
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>{
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>if (depObj != null)
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>{
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>foreach (object rawChild in LogicalTreeHelper.GetChildren(depObj))
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>{
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>if (rawChild is DependencyObject)
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>{
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>DependencyObject child = (DependencyObject)rawChild;
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>if (child is T)
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>{
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>yield return (T)child;
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>}

<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>foreach (T childOfChild in <strong>FindLogicalChildren</strong><T>(child))
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>{
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>yield return childOfChild;
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>}
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>}
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>}
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>}
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>}这样我们如果需要获取父控件类下面所有的TextBox控件列表,只需要如下操作即可。
//文本控件
var texboxList = <strong>FindLogicalChildren</strong><TextBoxBase>(depObj);
foreach (var textbox in texboxList)
{
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>if (textbox != null && !textbox.IsReadOnly)
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>{
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>textbox.TextChanged += (s, e) => { <strong>MainModelHelper.SetIsDirty</strong>(true); };//文本变化触发
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>}
}其他控件也是类似的方式处理,例如对于CheckBox和RadioButton,可以对它们共同的基类进行一并处理,如下所示。
//ToggleButton,包含CheckBox、RadioButton
var buttonList = FindLogicalChildren<ToggleButton>(depObj);
foreach (var toggle in buttonList)
{
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>if (toggle != null && toggle.IsEnabled)
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>{
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>toggle.Checked += (s, e) => { MainModelHelper.SetIsDirty(true); };//选择变化触发
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>toggle.Unchecked += (s, e) => { MainModelHelper.SetIsDirty(true); };//选择变化触发
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>}
}这样我们把它放到一个静态的辅助类里面方便使用,如下所示。
/// <summary>
/// 对WPF控件的相关处理,包括遍历查找等
/// </summary>
public static class ControlHelper
{
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>/// <summary>
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>/// 对界面的控件遍历,并监测状态变化
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>/// </summary>
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>/// <param name="depObj">父节点控件</param>
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>public static void SetDirtyEvent(DependencyObject depObj)
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>{
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>//如果全局禁用,则不跟踪脏数据状态
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>if (App.ViewModel!.DisableDirtyMessage)
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>return;

<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>#region 对控件类型进行监控

<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>//文本控件
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>var texboxList = FindLogicalChildren<TextBoxBase>(depObj);
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>foreach (var textbox in texboxList)
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>{
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>if (textbox != null && !textbox.IsReadOnly)
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>{
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>textbox.TextChanged += (s, e) => { MainModelHelper.SetIsDirty(true); };//文本变化触发
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>}
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>}
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>//下拉列表
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>var selectorList = FindLogicalChildren<Selector>(depObj);
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>foreach (var selector in selectorList)
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>{
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>var selectorType = selector.GetType();
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>if (selector != null && selector.IsEnabled &&
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>   selectorType != typeof(TabControl) && selectorType != typeof(ListBox)) //排除TabControl和ListBox选择触发
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>{
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>selector.SelectionChanged += (s, e) => { MainModelHelper.SetIsDirty(true); };//选择变化触发
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>}
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>}
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>//ToggleButton,包含CheckBox、RadioButton
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>var buttonList = FindLogicalChildren<ToggleButton>(depObj);
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>foreach (var toggle in buttonList)
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>{
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>if (toggle != null && toggle.IsEnabled)
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>{
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>toggle.Checked += (s, e) => { MainModelHelper.SetIsDirty(true); };//选择变化触发
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>toggle.Unchecked += (s, e) => { MainModelHelper.SetIsDirty(true); };//选择变化触发
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>}
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>}
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>#endregion
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>}因此,对于窗口的控件的编辑状态跟踪,我们可以在窗口的Loaded或者ContentRendered中实现跟踪即可,我这里实现覆盖OnContentRendered的方式,来对窗口控件的统一跟踪。
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>/// <summary>
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>/// 该事件在loaded之后执行,也是在所有元素渲染结束之后执行
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>/// </summary>
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>protected override void OnContentRendered(EventArgs e)
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>{
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>base.OnContentRendered(e);//初始化后默认脏数据状态为false
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>App.ViewModel!.IsDirty = false;
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>//对控件变化进行跟踪, 遍历父级及子级节点
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>ControlHelper.SetDirtyEvent(this);
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>//如果修改内容,对退出窗口进行确认
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>this.Closing += (s, e) =>
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>{
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>var isDisableDirty = App.ViewModel!.DisableDirtyMessage; //是否禁用了脏数据提示
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>var isDirty = App.ViewModel!.IsDirty;
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>if (!isDisableDirty && isDirty)
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>{
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>//数据已脏,提示确认
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>if (MessageDxUtil.ShowYesNoAndWarning("界面控件数据已编辑过,是否确认丢弃并关闭窗口") != System.Windows.MessageBoxResult.Yes)
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>{
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>e.Cancel = true;
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>}
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>else
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>{
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>App.ViewModel!.IsDirty = false;//取消脏数据状态
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>GrowlUtil.ClearTips(); //清空提示
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>}
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>}
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>};
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>}但是每个编辑窗口这样做,肯定是代码冗余的,我们优化一下,把逻辑抽取到一个独立的辅助类里面处理,这里改进后代码如下所示。
/// <summary>
/// 该事件在loaded之后执行,也是在所有元素渲染结束之后执行
/// </summary>
protected override void OnContentRendered(EventArgs e)
{
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>base.OnContentRendered(e);

<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>//在窗口准备完成后,对控件的内容变化进行监控,如修改过则退出确认
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>ControlHelper.SetDirtyWindow(this);
}这样在页面关闭的时候,我们提示用户即可。

当然,我们在主窗口视图模型里面也是设置了一个总开关,不需要的时候,关闭它即可。
<strong>App.ViewModel!.DisableDirtyMessage</strong> 我们在上面的代码逻辑中也可以看到,我们如果确认丢弃修改内容,那么状态重置,并清空一些提示信息即可。
<strong>App.ViewModel!.IsDirty</strong> = false;//取消脏数据状态
GrowlUtil.ClearTips(); //清空提示我们前面说到窗口对象的注入都是以Transient的方式,窗口的打开都是以每次构建新对象的方式,视图模型则是共享方式,因此,我们打开窗口的操作如下所示。
/// <summary>
/// 批量添加页面处理
/// </summary>

private void BatchAdd()
{
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>if (this.ViewModel.SelectDictType == null)
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>{
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>GrowlUtil.ShowInfo("请选择大类再添加项目");
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>return;
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>}

<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>//获取新增、编辑页面接口
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>var page = App.<strong>GetService<BatchAddDictDataPage></strong>();
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>page!.ViewModel.DictType = this.ViewModel.SelectDictType;
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>page!.ViewModel.Item = new BatchAddDictDataDto();

<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>//模态对话框打开
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>page.<strong>ShowDialog</strong>();
}通过GetService的方式获取新的一个窗口对象,并赋值对应的视图模型即可,然后打开模态对话框界面。
如果用户关闭,则会丢弃该对象,下次请求就是一个新的窗口实例了。
另外,我们窗口还可以配置快捷键ESC来关闭窗口,等同于按下关闭按钮的处理。我们在页面的Xaml文件中增加按键的绑定事件即可,如下代码所示。
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>其中的BackCommand就是我们预设页面关闭的方法。
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>///<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings> /// 关闭窗体<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>///<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings> <Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>private void Back()<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>{<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>this.Close();<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>}对于通用的导入窗口,我们也是一样的处理方式,我们通过一些事件的定义,把一些实现逻辑放在调用类上实现也可以的。
<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>///<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings> /// 导出内容到Excel<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>///<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings> <Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>private void ImportExcel()<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>{<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>var page = App.GetService();<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>page!.ViewModel.Items?.Clear();<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>page!.ViewModel.TemplateFile = $"系统用户信息-模板.xls";<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>page!.OnDataSave -= ExcelData_OnDataSave;<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>page!.OnDataSave += ExcelData_OnDataSave;<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>//模态对话框打开<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings><Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>page.ShowDialog();<Window.InputBindings>
    <KeyBinding
      Key="Esc"
      Command="{Binding BackCommand}"
      Modifiers="" />
</Window.InputBindings>}例如上面红色部分的事件,我们就是放在调用类中差异化处理。

这样就可以差异化不同的内容,同时保留通用模块的灵活性,导入界面如下所示。

 

来源:https://www.cnblogs.com/wuhuacong/archive/2023/09/21/17720116.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: 循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(6)