這聽起來像特定於視圖的邏輯,所以我沒有理由不使用視圖後面的代碼來控制它。就我個人而言,我會在TextBox
上執行PreviewKeyDown
這種行爲,它會丟棄任何非數字字符。
它可能不會傷害有一些通用的,你可以重複使用,如自定義NumbersOnlyTextBox
控制,或AttachedProperty
你可以連接到您的TextBox
指定只允許數字。
事實上,我記得創建一個附加屬性,允許您指定一個文本框的正則表達式,它將限制字符輸入到正則表達式。我有一段時間沒有使用它,所以你可能想要測試它或者更新它,但這裏是代碼。
// 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重新評估綁定,但老實說這不是一個理想的解。
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當PropertyChange通知被引發時,UI知道值實際上沒有改變,所以它不必費心去重新評估綁定並刷新UI。請參閱我的回答更新:) – Rachel
如果以這種方式工作,最終會出現無限循環:鍵入一個鍵將更改文本框,該文本框設置屬性,該屬性將觸發PropertyChanged事件,該事件將更新綁定,這將改變文本框,這將設置屬性......等等無限。 –