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 事件不仅会针对当前单元格(在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. 当前单元格:编辑开始为假
  2. 当前单元格:Tab 事件触发
  3. 下一个单元格:调用 Edit()
  4. 下一个单元格:编辑设置为 True
  5. 下一个单元格:调用 EditGate.WaitOne()
  6. 下一个单元格:Keyboard.Focus() 调用
  7. 当前单元格:焦点丢失(编辑仍然是错误的)
  8. 下一个单元格:Textbox.SelectAll() 调用
  9. 下一个单元格:调用 EditGate.Set()
  10. 下一个单元格:编辑设置为 False
  11. 下一个单元格:失去焦点(编辑现在是错误的)

我不确定为什么 LostFocus 事件会在其他所有事件之后触发。它几乎就像它知道我要做什么一样。:P

4

1 回答 1

1

我认为这可能是由于KeyboardFocus,在 WPF 中,您可以设置“逻辑”焦点,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 焦点时遇到问题,我猜是因为这不是它的设计工作方式,使用 Xaml 触发器对焦点进行排序可能会更好(如果可能的话)

也许 FocusManager 类可能会有所帮助,在这里您可以添加删除当前/下一个项目的焦点处理程序,

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