1

Is there some elegant way how to allow pasting into WPF TextBox that has AcceptsTab set to false while preserving tabs in the pasted text ?

When AcceptsTab is true, then user can't use tabs to move to next control, which isn't desired by my users. But they want to have tabs that are pasted, which currently are replaced by spaces.

Thank you

Emond
  • 50,210
  • 11
  • 84
  • 115

2 Answers2

2

I am not sure this qualifies as elegant but it works but might not be as complete as you want (e.g. when right-clicking in the textbox and selecting Paste from the context menu).

See Paste Event in a WPF TextBox

Set the AcceptsTab to true just before Ctrl-V is processed and restore it after:

XAML:

<TextBox AcceptsTab="False"
         Height="200" 
         PreviewKeyDown="TextBox_PreviewKeyDown" 
         KeyUp="TextBox_KeyUp"/>

C#:

private void TextBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
    if (!(sender is TextBox textbox))
    {
        return;
    }

    if (e.Key == Key.V && (e.KeyboardDevice.IsKeyDown(Key.LeftCtrl) || e.KeyboardDevice.IsKeyDown(Key.RightCtrl)))
    {
        textbox.AcceptsTab = true;
    }
}

private void TextBox_KeyUp(object sender, KeyEventArgs e)
{
    if (!(sender is TextBox textbox))
    {
        return;
    }

    textbox.AcceptsTab = false;
}

This could be turned into a behavior so it would be easier to apply it to more textboxes without writing code behind.

Emond
  • 50,210
  • 11
  • 84
  • 115
1

Another approach is by setting AcceptsTab to true and moving the focus when (Shift) Tab is pressed.

The nice side effect is that all the copy/paste scenarios will still function but the user will not be able to type a tab.

private void TextBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
    if (e.Key == Key.Tab)
    {
        var textBox = sender as TextBox;
        if (textBox != null)
        {
            var direction =
                e.KeyboardDevice.IsKeyDown(Key.LeftShift) || e.KeyboardDevice.IsKeyDown(Key.RightShift)
                    ? FocusNavigationDirection.Previous
                    : FocusNavigationDirection.Next;
            textBox.MoveFocus(new TraversalRequest(direction));
        }
    }
}
Emond
  • 50,210
  • 11
  • 84
  • 115