0

各セルに編集可能なテキスト ブロックを含むカスタム グリッド コントロールを作成しました。編集は、次のようにダブルクリックするとトリガーされます。

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();
    });
}

この部分は期待どおりに機能します。

タブを押して進むか、タブをシフトして戻るだけで、ユーザーが次のセルに移動できるようにしたいと考えていました。次のようにトリガーされるイベントを追加しました。

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));
    }
}

外側のグリッドはこのイベントを処理Edit()し、次または前の編集可能なセルでメソッドを呼び出します。これは、実際にテキスト ボックスに入力しない限り、ほとんど期待どおりに機能します。何かを入力すると、何らかの理由で LostFocus イベントが現在のセル ( Textbox のEdit()呼び出し後に予想される) だけでなく、次のセルでも発生します。Focus()LostFocus イベントのコードは次のとおりです。(関連性がないことは確かですが。)

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();
}

テキストボックスにこのイベントを無視させるために、ある種の派手なゲートを作成することもできますが、なぜそれが発生しているのか、または少なくとも答えを見つける方法についてもっと知りたいです。

ありがとう。

編集:

どうやら、ゲーティングがあっても、私はまだうんざりしています。というブール値を追加し、メソッドを次のようにEditing変更しました。Edit()

public void Edit()
{

    TextBox.Text = TextBlock.Text;
    TextBlock.Visibility = System.Windows.Visibility.Collapsed;
    TextBox.Visibility = System.Windows.Visibility.Visible;

    Thread Task = new Thread(() =>
    {
        Editing = true;
        Dispatcher.BeginInvoke((ThreadStart)delegate
        {
            System.Windows.Input.Keyboard.Focus(TextBox);
            TextBox.SelectAll();
            EditGate.Set();
        });
        EditGate.WaitOne();
        Editing = false;
    });
    Task.Start();
}

そして、LostFocus ハンドラーを変更しました。

void TextBox_LostFocus(object sender, RoutedEventArgs e)
{
    if (Editing) return;

    // ... Some more code.
}

残念ながら、これもうまくいきません。物事は次のようになります。

  1. 現在のセル: 編集は false として開始されます
  2. 現在のセル: タブ イベントの発生
  3. 次のセル: Edit() が呼び出されました
  4. 次のセル: True に設定された編集
  5. 次のセル: EditGate.WaitOne() が呼び出されました
  6. 次のセル: Keyboard.Focus() が呼び出されました
  7. 現在のセル: フォーカスが失われました (編集はまだ false です)
  8. 次のセル: Textbox.SelectAll() が呼び出されました
  9. 次のセル: EditGate.Set() が呼び出されました
  10. 次のセル: False に設定された編集
  11. 次のセル: フォーカスが失われました (編集は false になりました)

LostFocus イベントが他のすべての後に発生する理由がわかりません。私が何をしようとしているかを知っているようです。:P

4

1 に答える 1

1

私はそれが原因であると思います.WPFKeyboardFocusでは「論理」フォーカスを設定できますが、KeyboardFocusそれは単なる推測ですが、TextBoxに入力するKeyBoardFocusと、論理フォーカスの状態を変更する可能性のあるを取得しています。

テストするのは少し難しいですが、Edit()メソッドでキーボードフォーカスを設定して、何が起こるかを確認してください。

public void Edit()
{
    TextBox.Text = TextBlock.Text;
    TextBlock.Visibility = System.Windows.Visibility.Collapsed;
    TextBox.Visibility = System.Windows.Visibility.Visible;
    Dispatcher.BeginInvoke((ThreadStart)delegate
    {
        Keyboard.Focus(TextBox);
        TextBox.SelectAll();
    });
}

コード ビハインドから WPF フォーカスを操作する際に常に問題が発生していました。

おそらく、FocusManager クラスが役立つかもしれません。ここで、現在/次のアイテムのフォーカス ハンドラを追加して削除できます。

 FocusManager.RemoveLostFocusHandler(TextBox, TextBox_LostFocus);
 FocusManager.AddLostFocusHandler(TextBox, TextBox_LostFocus);
于 2013-02-12T02:50:52.003 に答える