title: Having trouble figuring out why a control is losing focus
body: <p>I've created a custom grid control with editable text blocks in each cell. The edit is triggered by a double click like so:</p>
  
  <pre><code>void TextBlock_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
  {
      if (e.ClickCount == 2) Edit();
  }
  
  public void Edit()
  {
      TextBox.Text = TextBlock.Text;
      TextBlock.Visibility = System.Windows.Visibility.Collapsed;
      TextBox.Visibility = System.Windows.Visibility.Visible;
      Dispatcher.BeginInvoke((ThreadStart)delegate
      {
          TextBox.Focus();
          TextBox.SelectAll();
      });
  }
  </code></pre>
  
  <p>This part works as expected.</p>
  
  <p>I wanted to give the user the ability to tab to the next cell simply by pushing tab to advance or shift tab to go back. I added an event which is triggered like so:</p>
  
  <pre><code>void TextBox_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
  {
      if (e.Key == System.Windows.Input.Key.Tab)
      {
          e.Handled = true;
          OnTab(System.Windows.Input.Keyboard.IsKeyDown(System.Windows.Input.Key.LeftShift) || System.Windows.Input.Keyboard.IsKeyDown(System.Windows.Input.Key.RightShift));
      }
  }
  </code></pre>
  
  <p>The outer grid handles this event and calls the <code>Edit()</code> method on the next or previous editable cell. This almost works as expected <em>as long as I don't actually type in the text box</em>. For some reason if I've typed anything the LostFocus event fires not only for the current cell (which is expected after <code>Edit()</code> calls <code>Focus()</code> on the Textbox) but for the next cell as well. Here's the code for the LostFocus event. (Though I'm pretty certain it's not relevant.)</p>
  
  <pre><code>void TextBox_LostFocus(object sender, RoutedEventArgs e)
  {
      bool TextChanged = TextBox.Text != TextBlock.Text;
      TextBlock.Text = TextBox.Text;
      TextBlock.Visibility = System.Windows.Visibility.Visible;
      TextBox.Visibility = System.Windows.Visibility.Collapsed;
      if (TextChanged) OnTextChanged();
  }
  </code></pre>
  
  <p>I could create some sort of fancy gate to get the textbox to ignore this event but I'm more curious as to why it's even firing, or at least how I could go about finding an answer.</p>
  
  <p>Thanks.</p>
  
  <p><strong>EDIT:</strong></p>
  
  <p>So apparently even with some gating I'm still hosed. I added a boolean called <code>Editing</code> and altered the <code>Edit()</code> method to work like this:</p>
  
  <pre><code>public void Edit()
  {
  
      TextBox.Text = TextBlock.Text;
      TextBlock.Visibility = System.Windows.Visibility.Collapsed;
      TextBox.Visibility = System.Windows.Visibility.Visible;
  
      Thread Task = new Thread(() =&gt;
      {
          Editing = true;
          Dispatcher.BeginInvoke((ThreadStart)delegate
          {
              System.Windows.Input.Keyboard.Focus(TextBox);
              TextBox.SelectAll();
              EditGate.Set();
          });
          EditGate.WaitOne();
          Editing = false;
      });
      Task.Start();
  }
  </code></pre>
  
  <p>And then changed the LostFocus handler:</p>
  
  <pre><code>void TextBox_LostFocus(object sender, RoutedEventArgs e)
  {
      if (Editing) return;
  
      // ... Some more code.
  }
  </code></pre>
  
  <p>Unfortunately this doesn't work either. Things end up going like so:</p>
  
  <ol>
  <li>Current Cell: Editing starts off as false</li>
  <li>Current Cell: Tab Event Fires</li>
  <li>Next Cell: Edit() called</li>
  <li>Next Cell: Editing set to True</li>
  <li>Next Cell: EditGate.WaitOne() called</li>
  <li>Next Cell: Keyboard.Focus() called</li>
  <li>Current Cell: Focus Lost (Editing is still false)</li>
  <li>Next Cell: Textbox.SelectAll() called</li>
  <li>Next Cell: EditGate.Set() called</li>
  <li>Next Cell: Editing set to False</li>
  <li>Next Cell: Focus Lost (Editing is now false)</li>
  </ol>
  
  <p>I'm not sure why the LostFocus event is firing <em>after</em> everything else. It's almost like it knows what I'm trying to do. :P</p>