WPF窗口库:自动化数据验证与保存提示

在大多数程序中,用户需要在一些窗口中输入数据,这些数据需要由控件进行验证。只有当所有必需的数据都输入后,用户才能保存。如果他更改了一些数据但尚未保存,当他关闭窗口时,会收到警告,提示他可能会丢失数据。如果所有这些功能都能自动添加到所有窗口中,而不需要编写太多代码,那岂不是很好?

WpfWindowsLib提供了这种功能。本文描述了其功能以及如何使用它。WpfWindowsLib是为.NET Core3.1及更高版本编写的。

用户体验

这里展示的窗口可能不是见过的最漂亮的窗口,但目的是系统地展示各种控件在不同状态下如何显示给用户。每一行都显示了相同的控件类型三次。在第一列中,每个控件都是空的。在第二列中,控件也是空的,但用户必须在可以按下保存按钮之前输入一些数据。在第三列中,控件有一些初始数据。

用户现在必须至少填写所有必填字段。只有这样,保存按钮才会启用。一旦他按下了保存按钮,它就会再次被禁用。如果用户随后更改了任何数据,保存按钮将再次启用。一个启用的保存按钮告诉用户他已经更改了一些数据。

如果用户在保存更改之前尝试关闭窗口会发生什么?他会收到一个警告消息,窗口会显示他更改了哪些数据但尚未保存。然后他可以决定是否要关闭窗口并放弃更改,或者是否要继续输入数据并可能保存更改。

使用代码

可以几乎不用编码就获得所有这些功能。WpfWindowsLib库提供了控件,它们:

  • 知道它们的数据何时发生了变化
  • 知道它们的数据何时未发生变化(用户撤销了他的更改)
  • 知道何时缺少“必需”控件的数据
  • 知道何时“必需”控件有数据
  • 自动找到它们所在的窗口并通知窗口每次状态变化

那个窗口必须继承自WpfWindowsLib中的CheckedWindow。

<wwl:CheckedWindow x:Class="Samples.SampleWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:wwl="clr-namespace:WpfWindowsLib;assembly=WpfWindowsLib"> <StackPanel> <wwl:CheckedTextBox x:Name="TestCheckedTextBox" MinWidth="100" MaxLength="20" IsRequired="True" /> <Button x:Name="SaveButton" Content="_Save" /> </StackPanel> </wwl:CheckedWindow>

继承自TextBox,添加了ICheck功能(见下文解释)和IsRequired属性。当设置为true时,用户必须提供一个值(即Text.Length>0)才能使保存按钮可用:

using System.Windows; using WpfWindowsLib; namespace Samples { public partial class SampleWindow : CheckedWindow { public SampleWindow() { InitializeComponent(); // 这里写一些代码来显示来自数据库的数据,等等。 TestCheckedTextBox.Text = database.Read(...); SaveButton.Click += saveButton_Click; updateSaveButtonIsEnabled(); } private void saveButton_Click(object sender, RoutedEventArgs e) { // 这里写一些代码来保存用户输入的数据 database.Write(..., TestCheckedTextBox.Text); Close(); } private void updateSaveButtonIsEnabled() { SaveButton.IsEnabled = HasICheckChanged && IsAvailable; } protected override void OnICheckChanged() { updateSaveButtonIsEnabled(); } protected override void OnIsAvailableChanged() { updateSaveButtonIsEnabled(); } } }

窗口的外观没有要求。但很可能,会有一个保存按钮。当一些数据发生了变化(=HasICheckChanged)并且所有必需的数据都已输入(=IsAvailable)时,这个按钮就会被启用。调用updateSaveButtonIsEnabled()。

使用的控件需要提供ICHeck接口的功能。WpfWindowsLib提供了以下控件:

  • AutoCompleteBox
  • CheckBox
  • ComboBox
  • DatePicker
  • DecimalTextBox
  • EmailTextBox
  • IntegerTextBox
  • PhoneTextBox
  • TextBox

不仅可以使用这些控件,还可以从任何现有控件继承并添加一个IChecker,它实现了ICHeck接口功能:

namespace WpfWindowsLib { public interface ICheck { bool HasChanged { get; } bool IsRequired { get; } bool IsAvailable { get; } event Action HasChangedEvent; event Action IsAvailableEvent; void ResetHasChanged(); void ShowChanged(bool isChanged); } }

在初始化期间,ICheck控件会搜索它所在的窗口。如果该窗口继承自CheckedWindow,它会注册到该窗口。在注册过程中,CheckedWindow会订阅控件的HasChangedEvent和IsAvailableEvent事件。

当用户随后更改控件中的一些数据,并且这导致HasChanged或IsAvailable发生变化时,控件会触发相应的事件,提醒CheckedWindow。CheckedWindow查询所有注册的控件,以评估其自己的HasICheckChanged或IsAvailable属性是否需要更改,然后调用OnICheckChanged和OnIsAvailableChanged,这使得继承的窗口有机会相应地启用或禁用保存按钮。

当用户尝试关闭窗口时,CheckedWindow会检查是否有任何控件有未保存的数据。如果有,它会标记这些控件,以便用户可以看到哪些尚未保存。然后CheckedWindow会询问用户是否真的想关闭窗口并丢失输入的数据。

获取WpfWindowsLib

最新版本可在Github上获得:

  • WpfWindowsLib:(.Dll)从其他解决方案中引用
  • Samples:WPFCore应用程序,展示所有WpfWindowsLib控件
  • WpfWindowsLibTest:包含一些WpfWindowsLib单元测试
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485