本文介绍了如何跟踪 WPF 的 TextBox 中删除了哪个字符?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想跟踪用户通过 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:

  1. 在选择多个字符时使用 Delete 键
  2. 退格键的使用
  3. 使用 Ctrl-X 进行剪切
  4. 点击菜单栏上的剪切"按钮

正因为如此,它比简单地拦截 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 中删除了哪个字符?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

05-30 07:20