I'm very new to .Net and WPF and have a problem. The code is a snippet. I have TextBox
es to enter dates. I check on correct input using GotFocus
and LostFocus
events.
<TextBox Name="sdDay" Width="40" Text="Day" GotFocus="DateDay_GotFocus" LostFocus="DateDay_LostFocus" Padding="5,5,5,5" HorizontalContentAlignment="Center" Focusable="True"/>
<TextBox Name="sdMonth" Width="50" Text="Month" GotFocus="DateMonth_GotFocus" LostFocus="DateMonth_LostFocus" Padding="5,5,5,5" Margin="5,0,0,0" HorizontalContentAlignment="Center" Focusable="True"/>
<TextBox Name="sdYear" Width="50" Text="Year" GotFocus="DateYear_GotFocus" LostFocus="DateYear_LostFocus" Padding="5,5,5,5" Margin="5,0,0,0" HorizontalContentAlignment="Center" Focusable="True"/>
And the code:
private void DateDay_GotFocus(object sender, RoutedEventArgs e)
{
if (((TextBox)sender).Text == "Day")
((TextBox)sender).Text = string.Empty;
}
private void DateDay_LostFocus(object sender, RoutedEventArgs e)
{
if (((TextBox)sender).Text == string.Empty)
((TextBox)sender).Text = "Day";
else
CheckForCorrectDateDay((TextBox)sender);
}
private void CheckForCorrectDateDay(TextBox b)
{
int day = 0;
try
{
day = int.Parse(b.Text);
if (day < 0 || day > 31)
{
MessageBox.Show("Please enter a correct day.");
b.Text = string.Empty;
b.Focus();
}
}
catch (FormatException)
{
MessageBox.Show("Please enter a number.", "Incorrect Input", MessageBoxButton.OK, MessageBoxImage.Warning);
b.Text = string.Empty;
b.Focus();
}
catch (Exception)
{
throw;
}
}
Now what I want it to do is check for correct input, and if that fails, set the focus back to whatever TextBox
had an incorrect entry.
It doesn't work though. After I enter a number outside the range (or letter), the MessageBox
will show but the focus shifts to the next TextBox which is for entering the month.
What am I doing wrong?
Your technique for validation here is, to be frank, very poor. That said, I believe the problem is just that WPF is handling the tab after you've set focus, so it is setting focus back to the next item in the focus order.
A simple workaround would be to dispatch a separate message that is processed after the current message:
if (day < 0 || day > 31)
{
MessageBox.Show("Please enter a correct day.");
b.Text = string.Empty;
Dispatcher.BeginInvoke((ThreadStart)delegate
{
b.Focus();
});
}
Doing this ensures that WPF completely processes the LostFocus
event handler before it processes the separate message to set focus on the erroneous control.
In terms of how you could tackle this problem in a much nicer way, you could:
IDataErrorInfo
on the view modelTextBox
es in the UI to the corresponding properties on the view model (prerequisite: read up on WPF data binding)If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With