WpfWindowsLib eliminates a lot of boiler plate code needed for data entry windows. The controls verify user input (numbers, email address, phone number, ...) and inform the host window if any data has changed, i.e., saving is needed before the user can close the window. The user can only save the data once all required data is entered. Most of that functionality gets provided by just placing the controls on the window.
Table of Contents
In most programs, there are some windows where the user has to enter some data, which the controls should validate. Only once all required data is entered, can the user save it. If he has changed some data but not saved yet, he gets alerted that he might lose some data when he closes the window. Wouldn't it be nice if all that functionality gets added automatically to all your windows without you programming much?
WpfWindowsLib
provides this functionality. This article describes its functionality and how to use it. WpfWindowsLib
is written for .NET Core 3.1 and higher.
This might not be the most beautiful window you ever see, but the idea here is to show systematically how the various controls are displayed to the user in their different states. In every row, the same control type gets displayed 3 times. In the first column, each control is empty. In the second column, the control is also empty, but the user has to enter some data before he can press the Save button. In the third column, the controls have some initial data.
The user has now to fill in at least all the required fields. Only then, the Save button gets enabled. Once he has pressed the Save button, it gets disabled again. If the user then changes any data, the Save button is enabled again. An enabled Save button tells the user that he has changed some data.
What happens when the user tries to close the window before saving the changes?
He gets a warning message and the window shows him which data he has changed but not saved yet. He can then decide if he wants to close the window and discard the changes or if he wants to continue the data entry and possibly save the changes.
You can get all this functionality with hardly any coding. The WpfWindowsLib
library provides controls which:
- know when their data has changed
- know when their data has been unchanged (user undid his change)
- know when a "required" control is lacking data
- know when a "required" control has data
- automatically find the Window they are in and inform the Window about each state change
That window has to inherit from CheckedWindow
in the WpfWindowsLib
.
<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
inherits from TextBox
, adds the ICheck
functionality (see explanation below) and an IsRequired
property. When this is set to true
, the user has to provide a value (i.e., Text.Length>0
) before the Save button gets available:
As in XAML, also in the code behind, the window has to inherit from CheckedWindow
:
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();
}
}
}
Only very little code needs to get added to that window:
Save Button
There are no requirements how the window has to look like. But most likely, there will be a Save button. This button is enabled, when some data has changed (=HasICheckChanged
) and all required data is entered (=IsAvailable
).
Calling updateSaveButtonIsEnabled()
HasICheckChanged
and IsAvailable
are properties of CheckedWindow
. If they change, CheckedWindow
calls OnICheckChanged()
or OnIsAvailableChanged()
, which need to be overridden to update the Save button state.
The controls used need to provide the functionality of the ICHeck
interface. The WpfWindowsLib
provides the following controls:
AutoCompleteBox
CheckBox
ComboBox
DatePicker
DecimalTextBox
EmailTextBox
IntegerTextBox
PhoneTextBox
TextBox
One is not limited to just these controls, but can inherit from any existing control and add an IChecker
, which implements the ICheck
interface functionality:
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);
}
}
- During initialisation, the
ICheck
control searches the window it is placed on. If that window inherits from CheckedWindow
, it registers with that window. During that registration, the CheckedWindow
subscribes to the HasChangedEvent
and IsAvailableEvent
event of the control. - When the user then changes some data in the control and this leads to a change of
HasChanged
or IsAvailable
, the control raises the appropriate event, which alerts CheckedWindow
. CheckedWindow
queries all registered controls to evaluate if its own HasICheckChanged
or IsAvailable
properties need to change and then calls OnICheckChanged
and OnIsAvailableChanged
, which gives the inheriting window the chance, to enable or disable the Save button accordingly. - When the user tries to close the window,
CheckedWindow
checks if any control has unsaved data. If so, it marks those controls so the user can see what is not saved yet. CheckedWindow
then asks the user if he really wants to close the window and lose the entered data.
The latest version is available from Github: https://github.com/PeterHuberSg/WpfWindowsLib.
Download or clone everything to your PC, which gives you a solution WpfWindowsLib
with the following projects:
WpfWindowsLib
: (.Dll) to be referenced from your other solutions Samples
: WPF Core application showing all WpfWindowsLib
controls WpfWindowsLibTest
: with few WpfWindowsLib
unit tests
Recommended Reading
- 20th February, 2020: Initial version