This is unfortunately more of a hack than a solution, but I thought I would share it any way. I had the situation where I needed to validate the entered time into a masked textbox. The masked textbox is a Windows Form control, but I hosted it within a WPF window using the WIndowsFormsHost element. Lastly, for some reason I could not get the Leave event to fire, so I opted to use the TextChanged event with some additional logic, checking the length of the entered value before validating it.
Initially, for validating the time I tried using the Regex class found within the System.Text.RegularExpressions namespace. However, after more research I discovered the TryParseExact method within the TimeSpan class. I validate the time entered into the masked textbox like below.
TimeSpan time;
bool valid = TimeSpan.TryParseExact(theTime, "g",
CultureInfo.CurrentCulture, out time);
Where “theTime” is a string formatted like “hh:mm”. Works perfectly.
The TextChanged event fires when I set the mask for the textbox. Initially, I had set the mask via the XAML, however I wanted to prevent the time validation check from running unnecessarily. Therefore, I set the mask within Windows_Loaded event and stopped the TextChange event from firing before the mask was set. The below code was added to the Window_Loaded event of the window and is shown below how I did disabled and re-enabled the event.
maskedTimeTextBox.TextChanged -= new EventHandler(maskedTimeTextBox _TextChanged);
maskedTimeTextBox.Mask = "00:00";
maskedTimeTextBox.TextChanged += new EventHandler(maskedTimeTextBox _TextChanged);
I created a method called ValidateTime() and called it from the TextChanged event and later from the method where I save the value to the database.
try
{
if (maskedTimeTextBox.Text.Length > 4)
{
TimeSpan time;
bool success = TimeSpan.
TryParseExact(theTime, "g",
CultureInfo.CurrentCulture,
out time);
if(TimeSpan.TryParseExact(theTime, "g",
CultureInfo.CurrentCulture,
out time))
{
return success;
}
else
{
MessageBox.Show("Please enter time in hh:mm format.",
"Error", MessageBoxButton.OK,
MessageBoxImage.Error);
maskedTimeTextBox.Text = "";
return false;
}
}
return false;
}
catch (Exception ex)
{
System.Windows.MessageBox.Show(ex.Message,
"Error", MessageBoxButton.OK, MessageBoxImage.Error);
return false;
}
As I could not get the Leave event to fire, nor could I find another event to use that would occur once the entire time was entered and the user either entered Save or the control lost focus, I used the above logic within the TextChanged event.
I know that a valid time, in my context, will be 5 characters long as shown above, 11:55 is greater than 4 characters and only 5 are allowed due to the mask. So the validation will only happen if the time entered into the masked textbox is greater than 4.
I am thinking that I may need to bind the masked textbox Windows Form control to the WPF window in some way to get the Leave event to fire. However, like most developers we have deadlines and other constraints that keep us, on many occasions, from implementing the correct implementation. Nonetheless, the code does not fire unless required and the validation only checks when the entered time is likely to pass. The point it, the implementation may not be perfect but the ineffeciencies of this implementation have been overcome by some additional logic added to the Window_Loaded event and the ValidateTime() method.
If you can think of a better solution I’d like to hear from you, please leave a comment. If I find a better one in the future I will make the edit.