我有以下TextBox:
<TextBox Text="{Binding SearchString,
UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" />
Run Code Online (Sandbox Code Playgroud)
绑定到以下属性:
private string _searchString;
public string SearchString
{
get
{
return _searchString;
}
set
{
value = Regex.Replace(value, "[^0-9]", string.Empty);
_searchString = value;
DoNotifyPropertyChanged("SearchString");
}
}
Run Code Online (Sandbox Code Playgroud)
该类继承自实现的基类 INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected void DoNotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
Run Code Online (Sandbox Code Playgroud)
我只想要一个快速而肮脏的方法来禁止非整数文本框的非数字字符(我知道它不完整,只是为了演示).我不想仅仅通知有非法文本或任何内容,我想立即丢弃所有不允许输入的字符.
但是,TextBox表现得很奇怪.我仍然可以输入我想要的任何文字,它将显示为输入,例如"1aaa".即使在此示例中已将属性正确清除为"1",文本框仍显示"1aaa".只有当我输入一个会导致_searchString更改的实际数字时,它才会更新显示的文本,例如当我有"1aaa2"时它会正确地更新为"12".这是怎么回事?
这听起来像是特定于视图的逻辑,所以我认为没有理由不使用视图背后的代码来控制它。就我个人而言,我会使用丢弃任何非数字字符的PreviewKeyDown
on来实现这种行为。TextBox
拥有可以重用的通用控件(例如自定义控件)可能不会有什么坏处,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
Run Code Online (Sandbox Code Playgroud)
它会像这样使用:
<TextBox Text="{Binding SearchString, UpdateSourceTrigger=PropertyChanged}"
local:TextBoxHelpers.AllowedCharactersRegex="[0-9]" />
Run Code Online (Sandbox Code Playgroud)
但至于为什么它不会更新 UI。UI 知道该值实际上并未更改,因此在收到 PropertyChange 通知时无需重新评估绑定。
为了解决这个问题,您可以尝试暂时将该值设置为其他值,然后再将其设置为正则表达式值,并发出通知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");
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
344 次 |
最近记录: |