用于数据输入的基本WPF窗口功能
目录
WpfWindowsLib消除了数据输入窗口所需的许多样板代码。控件会验证用户输入(数字、电子邮件地址、电话号码等),并通知托管窗口是否有任何数据已更改,即,在用户关闭窗口之前需要进行保存。输入所有必需的数据后,用户只能保存数据。仅通过将控件放在窗口中就可以提供大多数功能。
介绍
在大多数程序中,有些窗口中用户必须输入一些数据,控件应对此进行验证。只有输入了所有必需的数据,用户才能保存它。如果他更改了一些数据但尚未保存,他会收到警告,说他关闭窗口时可能会丢失一些数据。如果无需进行过多编程就可以将所有功能自动添加到所有窗口中,那不是很好吗?
WpfWindowsLib提供此功能。本文介绍了其功能以及如何使用它。WpfWindowsLib是为.NET Core 3.1和更高版本编写的。
用户体验
这可能不是您看到过的最漂亮的窗口,但是这里的想法是系统地显示各种控件如何以不同的状态显示给用户。在每一行中,相同的控件类型将显示3次。在第一列中,每个控件为空。在第二列中,控件也为空,但是用户必须先输入一些数据,然后才能按“保存”按钮。在第三列中,控件具有一些初始数据。
用户现在必须至少填写所有必填字段。只有这样,“保存”按钮才会启用。他按下“保存”按钮后,它将再次被禁用。如果用户随后更改任何数据,则将再次启用“保存”按钮。启用的“保存”按钮告诉用户他已更改了一些数据。
当用户在保存更改之前尝试关闭窗口时会发生什么?
他收到警告消息,并且窗口显示他已更改但尚未保存的数据。然后,他可以决定是否要关闭窗口并放弃更改,或者是否要继续数据输入并可能保存更改。
使用代码
您几乎不需要任何编码即可获得所有这些功能。该WpfWindowsLib库提供了以下控件:
- 知道他们的数据何时更改
- 知道他们的数据何时保持不变(用户撤消了更改)
- 知道何时“required”控件缺少数据
- 知道何时“required”控件具有数据
- 自动找到它们所在的窗口,并通知窗口每个状态更改
该窗口必须继承中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>
CheckedTextBox从TextBox继承,添加ICheck功能(请参见下面的说明)和IsRequired属性。当设置为true时,用户必须在“保存”按钮可用之前提供一个值(即Text.Length>0):
与XAML一样,在后面的代码中,窗口也必须继承自CheckedWindow:
using System.Windows;
using WpfWindowsLib;
namespace Samples {
public partial class SampleWindow: CheckedWindow {
public SampleWindow() {
InitializeComponent();
//write some code here to display data coming from a database, etc.
TestCheckedTextBox.Text = database.Read(...);
SaveButton.Click += saveButton_Click;
updateSaveButtonIsEnabled();
}
private void saveButton_Click(object sender, RoutedEventArgs e) {
//write some code here to save the data the user has entered
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()
HasICheckChanged和IsAvailable是CheckedWindow的属性。如果他们改变,CheckedWindow调用OnICheckChanged()或者OnIsAvailableChanged(),这需要重写更新保存按钮状态。
幕后发生了什么
所使用的控件需要提供ICHeck接口的功能。WpfWindowsLib将提供下列控件:
- AutoCompleteBox
- CheckBox
- ComboBox
- DatePicker
- DecimalTextBox
- EmailTextBox
- IntegerTextBox
- PhoneTextBox
- TextBox
一个不仅限于这些控件,还可以从任何现有控件中继承并添加IChecker,以实现ICheck接口功能:
namespace WpfWindowsLib {
public interface ICheck {
/// <summary>
/// Has the user changed the initial value of the control ?
/// </summary>
bool HasChanged { get; }
/// <summary>
/// Needs the user to change the initial value of the control ?
/// </summary>
bool IsRequired { get; }
/// <summary>
/// Has the user changed the initial value of the required control ?
/// </summary>
bool IsAvailable { get; }
/// <summary>
/// Raised when the user changes the initial value of the control
/// or when the user undoes any change and
/// enters the initial value again.
/// </summary>
event Action HasChangedEvent;
/// <summary>
/// Raised when the user changes the initial value of the required value control
/// or when the user undoes
/// any change and enters the initial value again.
/// </summary>
event Action IsAvailableEvent;
/// <summary>
/// Tells the control to use the present value as initial value.
/// </summary>
void ResetHasChanged();
/// <summary>
/// Changes the background color of the control if its value is now
/// different than the initial value
/// and isChanged is true. If isChanged is false, the background color
/// gets displayed from when the
/// control got initialised.
/// </summary>
/// <param name="isChanged"></param>
void ShowChanged(bool isChanged);
}
}
- 在初始化期间,ICheck控件搜索其所在窗口。如果该窗口继承自CheckedWindow,则向该窗口注册。在该注册期间,CheckedWindow订阅者订阅控件的HasChangedEvent和IsAvailableEvent事件。
- 当用户然后更改控件中的某些数据并导致HasChanged或IsAvailable更改时,控件将引发相应的事件,该事件将发出警报CheckedWindow。CheckedWindow查询所有已注册控件以评估其控件HasICheckChanged或IsAvailable属性是否需要更改,然后调用OnICheckChanged和OnIsAvailableChanged,从而为继承窗口提供了启用或禁用“保存”按钮的机会。
- 当用户尝试关闭窗口时,CheckedWindow检查是否有任何控件具有未保存的数据。如果是这样,它将标记这些控件,以便用户可以看到尚未保存的内容。CheckedWindow然后询问用户是否真的要关闭窗口并丢失输入的数据。
获取WpfWindowsLib
可从Github获得最新版本:https://github.com/PeterHuberSg/WpfWindowsLib。
将所有内容下载或克隆到您的PC,这为您提供了以下项目的WpfWindowsLib解决方案:
- WpfWindowsLib:(.Dll)从其他解决方案中引用
- Samples:WPF Core应用程序显示所有WpfWindowsLib控件
- WpfWindowsLibTest:几乎没有WpfWindowsLib单元测试
推荐阅读