Невозможно использовать отмену в TextChanged
при использовании textbox.Undo (); я получаю следующую ошибку:
Не удается отменить или повторить, пока undo unit открыт.
теперь я понимаю, почему это так (потому что это активное событие undoable), но через какое событие я могу выполнить проверку на текстовом поле и отменить изменение, если пользователь набрал недопустимый символ?
3 ответов
вместо использования отмены и TextChanged, вы должны использовать PreviewTextInput
и DataObject.Pasting
событий. В PreviewTextInput
обработчик событий, set e.Handled
значение true, если введенный текст является недопустимым символом. В Pasting
обработчик события e.CancelCommand()
если вставленный текст является недействительным.
вот пример для текстового поля, который принимает только цифры 0 и 1:
XAML:
<Window x:Class="BinaryTextBox.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="133" Width="329">
<StackPanel>
<TextBox x:Name="txtBinary" Width="100" Height="24"
PreviewTextInput="txtBinary_PreviewTextInput"
DataObject.Pasting="txtBinary_Pasting"/>
</StackPanel>
</Window>
код:
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Input;
namespace BinaryTextBox
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void txtBinary_PreviewTextInput(object sender,
TextCompositionEventArgs e)
{
e.Handled = e.Text != "0" && e.Text != "1";
}
private void txtBinary_Pasting(object sender, DataObjectPastingEventArgs e)
{
if (!Regex.IsMatch(e.DataObject.GetData(typeof(string)).ToString(), "^[01]+$"))
{
e.CancelCommand();
}
}
}
}
ответить симбай подход, который я думаю, увольняют.
вы не можете вызвать отмену в TextChanged, потому что операция отмены все еще готовится текстовым полем. Кажется, что это работает иногда, а не в другое время, поэтому это предполагает, что существует условие гонки между сигналом о событии и завершением подготовки отмены.
однако вызов отмены, вызванный диспетчером, позволит текстовому полю завершить подготовку отмены. Вы можете проверьте результаты изменения текста, а затем решите, хотите ли вы сохранить или отменить изменение. Это может быть не лучший подход, но я попробовал его и взорвал кучу текстовых изменений и вставок в текстовое поле и не смог воспроизвести исключение.
"принятый ответ" Отлично подходит, только если вы хотите предотвратить ввод или вставку недопустимого символа, но в целом я часто делаю гораздо более сложную проверку ввода TextBox и хочу проверить окончательное текстовое значение. Свой нелегко различить окончательный текст из события предварительного просмотра, потому что для элемента управления ничего еще не произошло.
чтобы ответить на вопрос Terribad, в ответ симбай лучше и более емко в нескольких ситуациях.
tb.TextChanged =+ (sender, args ) =>
{
if(! MeetsMyExpectations(tb.Text) )
Dispatcher.BeginInvoke(new Action(() => tb.Undo()));
}
Я прочитал много диких приключений в проверке текстового поля, и это примерно так же просто, как я нашел.
вызовите отмену асинхронно из обработчика событий From the TextChanged:
Dispatcher.BeginInvoke(new Action(() => tb.Undo()))