更改文本框文本而不触发TextChanged事件

21

我的应用程序使用C#编写,其中有一个带有txt_TextChanged事件的Textbox

private void txt_TextChanged(object sender, EventArgs e)
{
  //Do somthin
}

但是我想要更改 txt.Text 的一个特定部分,而不触发 txt_TextChanged 事件。

txt.Text ="somthing" //Don't fire txt_TextChanged

我该怎么做?


1
TextBoxBase.OnTextChanged 方法会触发 TextChanged 事件。创建一个自定义的 TextBox 控件,重写 OnTextChanged 方法并控制何时触发事件和何时不触发。如果 Balanikas 的答案不适合您,那么您可以尝试这种方法。 - gp.
你必须使用ASP.NET吗?使用jQuery怎么样? - Nima Derakhshanjan
@NiMa 这是一个 WinForm 应用程序,不是 Web 应用程序。 - Ghasem
@AlexJolig 抱歉,是我的错。 - Nima Derakhshanjan
为什么不使用suspendlayout()和resumelayout()? - Saleh
8个回答

21

没有直接的方法可以防止文本属性触发事件,但是你的事件处理程序可以使用标志来确定是否执行任务。这可能比附加和分离事件处理程序更有效。可以通过页面内的变量或甚至是专门的类包装器来实现此操作。

使用变量:

skipTextChange = true;
txt.Text = "Something";

protected void TextChangedHandler(object sender, EventArgs e) {
  if(skipTextChange){ return; }
  /// do some stuffl
}

通过专用事件处理程序包装器

   var eventProxy = new ConditionalEventHandler<EventArgs>(TextBox1_TextChanged);
    TextBox1.TextChanged = eventProxy.EventAction;

    eventProxy.RaiseEvents = false;
    TextBox1.Text = "test";


    public void TextBox1_TextChanged(object sender, EventArgs e) {
       // some cool stuff;
    }

    internal class ConditionalEventHadler<TEventArgs> where TEventArgs : EventArgs
{
   private Action<object,TEventArgs> handler;

    public bool RaiseEvents {get; set;}

    public ConditionalEventHadler(Action<object, TEventArgs> handler)
    {
        this.handler = handler; 
    }

    public void EventHanlder(object sender, TEventArgs e) {
      if(!RaiseEvents) { return;}
      this.handler(sender, e);
    }
}

2
我选择了第一部分,不需要其余的内容。 - Ghasem

19
txt.TextChanged -= textBox1_TextChanged;  // dettach the event handler
txt.Text = "something"; // update value
txt.TextChanged += textBox1_TextChanged; // reattach the event handler

1
过了一会儿,我意识到这是完成这个技巧最简单的方法。 - Ghasem
对于PowerShell,这个操作类似:$txt.remove_TextChanged($textBox1_TextChanged)... - TNT
那是真实而简单的答案。 - Matheus Miranda

8
你可以扩展文本框并引入一个新属性,该属性不会触发TextChanged事件。
    class SilentTextBox : TextBox
    {
        // if true, than the TextChanged event should not be thrown
        private bool Silent { get; set; }

        public string SilentText
        {
            set
            {
                try 
                {
                    Silent = true;
                    Text = value;
                } 
                finally 
                {
                    Silent = false;
                }
            }
        }

        protected override void OnTextChanged(EventArgs e)
        {
            // raise event only if the control is in non-silent state
            if (!Silent)
            {
                base.OnTextChanged(e);
            }
        }
    }

6

试试这个扩展方法

  public static class TextBoxExt
{
    private static readonly FieldInfo _field;
    private static readonly PropertyInfo _prop;

    static TextBoxExt()
    {
        Type type = typeof(Control);
        _field = type.GetField("text", BindingFlags.Instance | BindingFlags.NonPublic);
        _prop = type.GetProperty("WindowText", BindingFlags.Instance | BindingFlags.NonPublic);
    }

    public static void SetText(this TextBox box, string text)
    {
        _field.SetValue(box, text);
        _prop.SetValue(box, text, null);
    }
}

您可以使用textbox.SetText("...")来更改文本,而TextChanged事件不会被触发。


1
一种快速而简单的方法是使用一个

标签。
ctrl.Enable = false; 
ctrl.Text = "Something";
ctrl.Enable = true;

然后在OnChange事件中,使用一个封装来包含有问题的代码

if (ctrl.Enabled) {
  // offending code here.
}

0
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        EventHandler TextChanged_EventHandler = new EventHandler(textBox1_TextChanged);
        textBox1.TextChanged -= TextChanged_EventHandler;
    }

    private void textBox1_TextChanged(object sender, EventArgs e)
    {
        MessageBox.Show("BUG");
    }
}

你可以通过将事件从控件中注销(使用EventHandler)来移除该事件。 - AsfK

0

我发现了一种简单的方法,适用于事件处理程序和不在同一个 .cs 文件中的控件。

public static void SetTextWithoutRaiseEvent(this TextBox textBox, string content)
{
    var scroll = textBox.Template.FindName("PART_ContentHost", textBox);
    (scroll as ScrollViewer).Content = content;
}

0
在WPF中,您可以使用以下代码:(与@Mitz类似的方式)
public static void SetText(this TextBox textbox, string text)
{
    textbox.GetType().GetProperty("Text").SetValue(textbox, text, null);
}

你可以像这样使用:MyTextBoxWithEvent.SetText("你好,世界");


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接