问题描述
我想通过 Delete 或 BackSpace 键跟踪用户删除了哪个字符.
I want to track which character is deleted by the user through Delete or BackSpace Key.
我正在处理文本框的 TextBox_ChangedEvent.
I am handling TextBox_ChangedEvent of textbox.
我可以从 TextChangedEventArgs e.Changes 中提取已删除的字符吗?如果是,我该怎么做?
Can I extract the deleted character from TextChangedEventArgs e.Changes and if yes How can I do that?
我想限制用户从文本框中删除任何字符.我希望用户只能删除两个字符(比如("或)")
I want to restrict user to from deleting any characters from the TextBox. I want user can delete only two characters ( let's say "(" or ")" )
请提出建议.
推荐答案
下面您将找到附加属性的代码,可以像这样使用以防止从 TextBox 中删除除("或)"之外的任何内容,期间.
Below you will find code for an attached property that can be used like this to prevent anything but "(" or ")" from being deleted from the TextBox, period.
<TextBox my:TextBoxRestriction.RestrictDeleteTo="()" ... />
这将正确处理所有鼠标和键盘更新,例如:
This will correctly handle all mouse and keyboard updates, such as:
- 在选择多个字符时使用 Delete 键
- 使用退格键
- 使用 Ctrl-X 进行剪切
- 点击菜单栏上的剪切"按钮
因此,它比简单地拦截 PreviewKeyDown 强大得多.
Because of this it is much more powerful than simply intercepting PreviewKeyDown.
这也会通过直接分配给 .Text 属性来禁止删除任何由("或)"组成的内容,因此这将失败:
This also disables deletion of anything byt "(" or ")" by assigning directly to the .Text property, so this will fail:
textBox.Text = "Good morning";
因此,TextBoxRestriction 类还包含另一个名为 UnrestrictedText 的附加属性,该属性在设置后能够绕过限制更新 Text 属性.这可以使用 TextBoxRestriction.SetUnrestrictedText
在代码中设置,或者像这样的数据绑定:
Because of this the TextBoxRestriction class also contains another attached property called UnrestrictedText which, when set, is able to update the Text property bypassing the restrictions. This can be set in code using TextBoxRestriction.SetUnrestrictedText
, or data-bound like this:
<TextBox my:TextBoxRestriction.RestrictDeleteTo="()"
my:TextBoxRestriction.UnrestrictedText="{Binding PropertyNameHere}" />
在下面的实现中,UnrestrictedText 仅在设置了 RestrictDeleteTo 时才有效.一个完整的实现可以在任何一个属性被设置时注册事件处理程序,并将处理程序保存在第三个附加属性中以供以后取消注册.但对于您当前的需求,这可能是不必要的.
In the implementation below, UnrestrictedText only works when RestrictDeleteTo is also set. A full implementation could be made that registers the event handler whenever either property is set and saves the handler in a third attached property for later unregistration. But for your current needs that is probably unnecessary.
这是承诺的实现:
public class TextBoxRestriction : DependencyObject
{
// RestrictDeleteTo: Set this to the characters that may be deleted
public static string GetRestrictDeleteTo(DependencyObject obj) { return (string)obj.GetValue(RestrictDeleteToProperty); }
public static void SetRestrictDeleteTo(DependencyObject obj, string value) { obj.SetValue(RestrictDeleteToProperty, value); }
public static readonly DependencyProperty RestrictDeleteToProperty = DependencyProperty.RegisterAttached("RestrictDeleteTo", typeof(string), typeof(TextBoxRestriction), new PropertyMetadata
{
PropertyChangedCallback = (obj, e) =>
{
var box = (TextBox)obj;
box.TextChanged += (obj2, changeEvent) =>
{
var oldText = GetUnrestrictedText(box);
var allowedChars = GetRestrictDeleteTo(box);
if(box.Text==oldText || allowdChars==null) return;
foreach(var change in changeEvent.Changes)
if(change.RemovedLength>0)
{
string deleted = box.Text.Substring(change.Offset, change.RemovedLength);
if(deleted.Any(ch => !allowedChars.Contains(ch)))
box.Text = oldText;
}
SetUnrestrictedText(box, box.Text);
};
}
});
// UnrestrictedText: Bind or access this property to update the Text property bypassing all restrictions
public static string GetUnrestrictedText(DependencyObject obj) { return (string)obj.GetValue(UnrestrictedTextProperty); }
public static void SetUnrestrictedText(DependencyObject obj, string value) { obj.SetValue(UnrestrictedTextProperty, value); }
public static readonly DependencyProperty UnrestrictedTextProperty = DependencyProperty.RegisterAttached("UnrestrictedText", typeof(string), typeof(TextBoxRestriction), new PropertyMetadata
{
DefaultValue = "",
PropertyChangedCallback = (obj, e) =>
{
var box = (TextBox)obj;
box.Text = (string)e.NewValue;
}
});
}
工作原理:当您设置 UnrestrictedText 时,它会设置 Text,反之亦然.TextChanged 处理程序会检查 Text 是否与 UnrestrictedText 不同.如果是这样,它知道 Text 已通过某种其他机制更新而不是设置 UnrestrictedText,因此它会扫描更改以查找非法删除.如果找到,它将 Text 设置回仍存储在 UnrestrictedText 中的值,以防止更改.
How it works: When you set UnrestrictedText it sets Text and vice versa. The TextChanged handler checks to see if Text is different than UnrestrictedText. If so, it knows that Text has been updated by some other mechanism than setting UnrestrictedText so is scans the changes for an illegal delete. If one is found it sets Text back to the value still stored in UnrestrictedText, preventing the change.
这篇关于如何跟踪在 WPF 中的 TextBox 中删除了哪个字符?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!