textbox.Undo(); を使用する場合 次のエラーが表示されます。
元に戻すユニットが開いている間は、元に戻すまたはやり直すことはできません。
なぜこれが事実なのか理解できました (アクティブな元に戻すことができるイベントであるため) が、ユーザーが無効な文字を入力した場合、どのイベントを介してテキスト ボックスの検証を実行し、変更を元に戻すことができますか?
却下されていると思うsimbayのアプローチに答えるために。
元に戻す操作がまだ TextBox によって準備されているため、TextChanged で Undo を呼び出すことはできません。動作する場合と動作しない場合があるため、イベントが通知されてから元に戻す準備が完了するまでの間に競合状態があることを示唆しています。
ただし、Dispatcher で呼び出された Undo を呼び出すと、テキスト ボックスは元に戻す準備を完了することができます。テキスト変更の結果を検証してから、変更を保持するか元に戻すかを決定できます。これは最善の方法ではないかもしれませんが、私はそれを試してみて、大量のテキストの変更と貼り付けをテキスト ボックスに吹き込みましたが、例外を再現できませんでした。
「受け入れられた回答」は、無効な文字が入力または貼り付けられるのを防ぎたい場合にのみ優れていますが、一般的に、TextBox 入力のより複雑な検証を行い、最終的なテキスト値を確認したい場合にのみ使用します。コントロールに関する限り、まだ何も起こっていないため、Preview イベントから最終的なテキストを識別するのは簡単ではありません。
Terribad の質問に答えるには、simbay の回答の方が優れており、より多くの状況でより簡潔です。
tb.TextChanged += ( sender, args ) =>
{
if(! MeetsMyExpectations( tb.Text ) )
Dispatcher.BeginInvoke(new Action(() => tb.Undo()));
};
私はテキスト ボックスの検証で多くのワイルドな冒険を読みましたが、これは私が見つけたのと同じくらい簡単です。
Undo および TextChanged を使用する代わりに、PreviewTextInput
およびDataObject.Pasting
イベントを使用する必要があります。PreviewTextInput
イベント ハンドラーで、入力されたテキストが無効な文字である場合は true に設定しe.Handled
ます。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();
}
}
}
}
From the TextChanged イベント ハンドラーから非同期的に取り消しを呼び出します。
Dispatcher.BeginInvoke(new Action(() => tb.Undo()))