Click here to Skip to main content
15,892,768 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
I have a wpf application where the user enters a work order number in a text box. In the lost focus event of the text box, a database is queried to validate that the work order number exists. If not, a message box is displayed and the Focus() method of the textbox control is called to keep the focus on that text box.

What actually happens is that the lost focus event fires repeatedly

Here is the xaml for the textbox control:

TextBox x:Name="txtWONumber" IsReadOnly="False" Focusable="True" HorizontalAlignment="Left" Height="23" Margin="174,15,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="120" RenderTransformOrigin="0.384,0.424" FocusManager.LostFocus="TxtWONumber_LostFocus"/>


Here is the event handler code:

private void TxtWONumber_LostFocus(object sender, RoutedEventArgs e)
		{

			string strWONumber = this.txtWONumber.Text;
			//MessageBox.Show("Work Order No: " + strWONumber);

			var qryWorkOrder =
			(from w in dataEntities.vwWOPatternCheckDatas	
			 where w.WONumber == strWONumber
			 orderby w.WONumber
			 select new { w.WONumber }).ToList();

			if (qryWorkOrder.Count() == 0)
			{
				MessageBox.Show("Work Order Number not found! Please enter a valid Work Order Number.");
				txtWONumber.Focus();
				txtWONumber.SelectAll();
			}
		}


Thank you,

Brian Miller

What I have tried:

I have tried using the LostFocus event as well as the FocusManager.LostFocus event and the behavior is the same.

I have spent a number of hours searching for relevant information on the web. Nothing seems to address this situation. The closest I have found is related to two consecutive text boxes in the tab order each with a lost focus event.
Posted
Updated 3-Mar-19 2:46am
Comments
Richard Deeming 5-Mar-19 12:35pm    
NB: Rather than counting all the matches to determine whether there are any, it's better to use either Any or All:
if (!dataEntities.vwWOPatternCheckDatas.Any(w => w.WONumber == strWONumber)) { ... }
// Or:
if (dataEntities.vwWOPatternCheckDatas.All(w => w.WONumber != strWONumber)) { ... }

I've encountered your situation with different languages.

The "next field" will receive "focus" while the previous field is "losing focus".

"Setting focus" while "losing focus" in the "lost focus" event gets problematic because of the "next field" focus logic.

The "work around" (in my case) was to ("simply") store the field name of the current field while losing focus, and at the same time in the next field's "got focus" to do a call to the "previous fields" validation logic. If it is valid, then "accept focus" of the new field, else reject the new focus whereupon the focus stays on the last field (e.g. Windows Forms has a "Can focus" property).

Haven't reviewed WPF (because I tend to do "record-level" validation more these days than "field-level") for an equivalent "can focus", but you can probably return focus to the previous field (from the next field) using the focus statement.

Note that if your "field" is at "end of your form", you may have to resort to a "record-level" validation anyway because now you may not lose focus at all (while "saving").

(Yeah; sounds ugly but such is life when you do something most people don't: field-level validation).

As for validating the "work order #": in those cases I usually employ a "pick list", as every major software product does. There are never that many "open" work orders that you cannot query the the db for a list of work orders numbers that can be "popped up" when the user hits that field.
 
Share this answer
 
v2
Comments
Member 12344083 3-Mar-19 13:35pm    
Thank you very much for the response. I made changes to the code to separate the validation logic and call that function from the got focus event of the next element, a list box.

That works, but there are a couple of concerns with this approach.

1. The validation code will run every time that list box receives the focus, even if it is not by exiting the text box that needs validated. Result would be an unnecessary query to the database.

2. User may skip the list box entirely by clicking on another control with the mouse. In this case, the got focus handler for the list box would never run and validation would not happen.
I think this is what's happening. You're showing a message, but immediately giving focus to the textbox again. Now, you have the message box open, and you want to click ok to close it, but then the textbox is losing focus again.

Maybe try the following:

private void TxtWONumber_LostFocus(object sender, RoutedEventArgs e)
		{
                        if (checkNumber) // Should number be checked
                        {
                            checkNumber = false;
        			string strWONumber = this.txtWONumber.Text;
        			//MessageBox.Show("Work Order No: " + strWONumber);
    
        			var qryWorkOrder =
        			(from w in dataEntities.vwWOPatternCheckDatas	
        			 where w.WONumber == strWONumber
        			 orderby w.WONumber
        			 select new { w.WONumber }).ToList();
    
        			if (qryWorkOrder.Count() == 0)
        			{
        				if (MessageBox.Show("Work Order Number not found! Please enter a valid Work Order Number.") == DialogResult.OK)
                                        {
                                		txtWONumber.Focus();
                        			txtWONumber.SelectAll();
                                                checkNumber = true;
                                        }
        			}
                        }
                        
		}



So, you have a global bool variable checkNumber which is set to true, that indicates that you want to check the works order number. Once it enters the if statement, you set it to false, and set it back to true after you've clicked the ok button on the message box.
 
Share this answer
 
v6
Comments
Member 12344083 3-Mar-19 12:32pm    
Thank you very much for the response. I should have noted in the question that the focus issue occurred even with the message box code commented out. The program appears to hang and stepping through the code shows that the lost focus event handler is being called repeatedly.

I tried your suggested change and it did not affect the behavior. I was hoping it would as yours was the clearest and simplest suggestion by far.
Dylvh 3-Mar-19 16:31pm    
You're welcome. I have updated the solution and hopefully it will help.
Rather using LostFocus, you might also think to create and use DependencyProperty of string type in code behind and bind it 2 way to Text property of TextBox. Dependency property provides a callback event that you can use to validate the text. Refer to below link for details on its usage

WPF Tutorial | Dependency Properties[^]
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900