Как предотвратить нажатие клавиши Backspace в TextBox?
Я хочу подавить нажатие клавиши в TextBox. Чтобы подавить все нажатия клавиш, кроме Backspace, я использую следующее:
private void KeyBox_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
e.Handled = true;
}
Однако я хочу подавлять нажатия клавиш только тогда, когда нажата клавиша Backspace. Я использую следующее:
if (e.Key == System.Windows.Input.Key.Back)
{
e.Handled = true;
}
Однако это не работает. Символ за началом выбора все еще удален. Я получаю "TRUE" в выводе, поэтому клавиша Back распознается. Как бы я запретил пользователю нажимать клавишу возврата? (Моя причина в том, что в некоторых случаях я хочу удалить слова вместо символов, и поэтому мне нужно самостоятельно нажимать клавишу "назад".)
8 ответов
Это правда, что не существует простого способа справиться с этим сценарием, но это возможно.
Вам необходимо создать некоторые переменные-члены в классе для хранения состояния входного текста, положения курсора и состояния нажатия клавиши "назад" при переходе между событиями KeyDown, TextChanged и KeyUp.
Код должен выглядеть примерно так:
string m_TextBeforeTheChange;
int m_CursorPosition = 0;
bool m_BackPressed = false;
private void KeyBox_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
m_TextBeforeTheChange = KeyBox.Text;
m_BackPressed = (e.Key.Equals(System.Windows.Input.Key.Back)) ? true : false;
}
private void KeyBox_TextChanged(object sender, TextChangedEventArgs e)
{
if (m_BackPressed)
{
m_CursorPosition = KeyBox.SelectionStart;
KeyBox.Text = m_TextBeforeTheChange;
}
}
private void KeyBox_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
{
KeyBox.SelectionStart = (m_BackPressed) ? m_CursorPosition + 1 : KeyBox.SelectionStart;
}
Просто установите e.SuppressKeyPress = true (в событии KeyDown), если вы хотите подавить нажатие клавиши. Например, не позволяйте клавише Backspace изменить текст в текстовом поле, используя следующий код:
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Back)
{
e.SuppressKeyPress = true;
}
}
В Silverlight нет способа обрабатывать системные системные события, такие как возврат. Таким образом, вы можете обнаружить это, но не обрабатывать это вручную.
Это требует, чтобы мы сохранили значение текстового поля до события нажатия клавиши. К сожалению, backspace обрабатывается до того, как это событие сработало, поэтому мы должны захватить его до того, как это произойдет, и затем мы можем обновить его снова после того, как событие key up продолжено.
private string textBeforeChange;
private void TextBox1_OnKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Back)
{
e.Handled = true;
textBox1.Text = textBeforeChange;
}
}
private void TextBox1_OnKeyUp(object sender, KeyEventArgs e)
{
textBeforeChange = textBox1.Text;
}
private void MainPage_OnLoaded(object sender, RoutedEventArgs e)
{
textBox1.AddHandler(TextBox.KeyDownEvent, new KeyEventHandler(TextBox1_OnKeyDown), true);
textBox1.AddHandler(TextBox.KeyUpEvent, new KeyEventHandler(TextBox1_OnKeyUp), true);
textBox1.AddHandler(TextBox.ManipulationStartedEvent, new EventHandler<ManipulationStartedEventArgs>(TextBox1_OnManipulationStarted), true);
}
private void TextBox1_OnManipulationStarted(object sender, ManipulationStartedEventArgs e)
{
textBeforeChange = textBox1.Text;
}
Вот что я придумал, чтобы удалить предыдущее (CtrlBackspace) и следующее слово (CtrlDelete), обрабатывая несколько последующих пробельных символов (0x09, 0x20, 0xA0):
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace DeleteWord
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
// Tab, space, line feed
char[] whitespace = {'\x09', '\x20', '\xA0'};
string text = textBox1.Text;
int start = textBox1.SelectionStart;
if ((e.KeyCode == Keys.Back || e.KeyCode == Keys.Delete) && textBox1.SelectionLength > 0)
{
e.SuppressKeyPress = true;
textBox1.Text = text.Substring(0, start) + text.Substring(start + textBox1.SelectionLength);
textBox1.SelectionStart = start;
return;
}
else if (e.KeyCode == Keys.Back && e.Control)
{
e.SuppressKeyPress = true;
if (start == 0) return;
int pos = Math.Max(text.LastIndexOfAny(whitespace, start - 1), 0);
while (pos > 0)
{
if (!whitespace.Contains(text[pos]))
{
pos++;
break;
}
pos--;
}
textBox1.Text = text.Substring(0, pos) + text.Substring(start);
textBox1.SelectionStart = pos;
}
else if (e.KeyCode == Keys.Delete && e.Control)
{
e.SuppressKeyPress = true;
int last = text.Length - 1;
int pos = text.IndexOfAny(whitespace, start);
if (pos == -1) pos = last + 1;
while (pos <= last)
{
if (!whitespace.Contains(text[pos])) break;
pos++;
}
textBox1.Text = text.Substring(0, start) + text.Substring(pos);
textBox1.SelectionStart = start;
}
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == Keys.Tab)
{
textBox1.Paste("\t");
return true;
}
else if (keyData == (Keys.Shift | Keys.Tab))
{
textBox1.Paste("\xA0");
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
}
}
Спасибо Хай Нгуену за e.SuppressKeyPress = true;
!
Если есть выделение, и Delete, и Backspace удалят выделение независимо от клавиш-модификаторов (вы не получите этот уродливый прямоугольный символ для удержания Ctrl)
Кажется, работает для символов, как также, хотя это может не иметь особого смысла (не является ли этот персонаж целым словом?)
Просто поместите этот текст в событие KeyDown textBox (пример: textBox18):
private void textBox18_KeyDown(object sender, KeyEventArgs e)
{
e.SuppressKeyPress = true; // cancels the typed character
if (e.KeyValue != 8) // checks if key typed is Backspace
{
e.SuppressKeyPress = false; // if it is not Backspace then reactivates/enables the typed character
}
}
Это простое решение, которое мне подходит.
private void MyTxtbox_Keypress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == '\b')
{
e.Handled = true;
return;
}
}
string oldText = "";
private void testTextBlock_TextChanged(object sender, TextChangedEventArgs e)
{
if (testTextBlock.Text.Length < oldText.Length)
{
testTextBlock.Text = oldText;
testTextBlock.SelectionStart = oldText.Length;
}
else
{
oldText = testTextBlock.Text;
}
}