これはビュー固有のロジックのように聞こえるので、ビューを制御するためにコードビハインドを使用しない理由はありません。個人的に私はPreviewKeyDown
のTextBox
に数字以外の文字を捨てて、この種の動作を実装します。 コントロールなどの一般的なものを持っていることや、TextBox
に添付して数値のみを許可することを指定できるAttachedProperty
などは、おそらく害ではないでしょう。
実際には、テキストボックスの正規表現を指定することができる添付プロパティを作成することを覚えています。文字入力をその正規表現だけに制限します。私はしばらくそれを使用していないので、おそらくそれをテストしたり、それを更新したりしたいと思うでしょうが、ここにコードがあります。
// When set to a Regex, the TextBox will only accept characters that match the RegEx
#region AllowedCharactersRegex Property
/// <summary>
/// Lets you enter a RegexPattern of what characters are allowed as input in a TextBox
/// </summary>
public static readonly DependencyProperty AllowedCharactersRegexProperty =
DependencyProperty.RegisterAttached("AllowedCharactersRegex",
typeof(string), typeof(TextBoxProperties),
new UIPropertyMetadata(null, AllowedCharactersRegexChanged));
// Get
public static string GetAllowedCharactersRegex(DependencyObject obj)
{
return (string)obj.GetValue(AllowedCharactersRegexProperty);
}
// Set
public static void SetAllowedCharactersRegex(DependencyObject obj, string value)
{
obj.SetValue(AllowedCharactersRegexProperty, value);
}
// Events
public static void AllowedCharactersRegexChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
var tb = obj as TextBox;
if (tb != null)
{
if (e.NewValue != null)
{
tb.PreviewTextInput += Textbox_PreviewTextChanged;
DataObject.AddPastingHandler(tb, TextBox_OnPaste);
}
else
{
tb.PreviewTextInput -= Textbox_PreviewTextChanged;
DataObject.RemovePastingHandler(tb, TextBox_OnPaste);
}
}
}
public static void TextBox_OnPaste(object sender, DataObjectPastingEventArgs e)
{
var tb = sender as TextBox;
bool isText = e.SourceDataObject.GetDataPresent(DataFormats.Text, true);
if (!isText) return;
var newText = e.SourceDataObject.GetData(DataFormats.Text) as string;
string re = GetAllowedCharactersRegex(tb);
re = "[^" + re + "]";
if (Regex.IsMatch(newText.Trim(), re, RegexOptions.IgnoreCase))
{
e.CancelCommand();
}
}
public static void Textbox_PreviewTextChanged(object sender, TextCompositionEventArgs e)
{
var tb = sender as TextBox;
if (tb != null)
{
string re = GetAllowedCharactersRegex(tb);
re = "[^" + re + "]";
if (Regex.IsMatch(e.Text, re, RegexOptions.IgnoreCase))
{
e.Handled = true;
}
}
}
#endregion // AllowedCharactersRegex Property
それはこのように使用されるでしょう:
<TextBox Text="{Binding SearchString, UpdateSourceTrigger=PropertyChanged}"
local:TextBoxHelpers.AllowedCharactersRegex="[0-9]" />
しかし、それはUIを更新しないであろう理由を。 UIは値が実際には変更されていないことを知っているので、PropertyChange通知を受け取ったときにバインドの再評価を行う必要はありません。
これを回避するには、値を正規表現の値に設定する前に一時的に別の値に設定し、UIがバインディングを再評価するようにPropertyChange
通知を呼び出すことができます。しかし、実際は理想的ではありません溶液。
private string _searchString;
public string SearchString
{
get
{
return _searchString;
}
set
{
value = Regex.Replace(value, "[^0-9]", string.Empty);
// If regex value is the same as the existing value,
// change value to null to force bindings to re-evaluate
if (_searchString == value)
{
_searchString = null;
DoNotifyPropertyChanged("SearchString");
}
_searchString = value;
DoNotifyPropertyChanged("SearchString");
}
}
あなたは正しいです。なぜそれがこのように動作しないのですか? – user1064519
@ user1064519 UIは、PropertyChange通知が発生したときに値が実際に変更されていないことを知っているため、バインディングを再評価してUIを更新する必要はありません。私の答えへの更新を参照してください:) – Rachel
この方法でうまくいけば、無限ループになります。キーを入力するとPropertyChangedイベントを発生させるプロパティを設定するテキストボックスが変更され、これはテキストボックスを変更し、プロパティを設定します...など、広告の無限になります。 –