Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/264.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在C#事件中区分代码更改或用户更改?_C#_Winforms - Fatal编程技术网

如何在C#事件中区分代码更改或用户更改?

如何在C#事件中区分代码更改或用户更改?,c#,winforms,C#,Winforms,我有一个简单的文本框,开头是空的。我有一个简单的事件_TextChanged,用来知道用户何时更改了文本框中的任何内容。但是,如果我自己从代码中对事件执行任何操作,就会触发该事件。如设置textbox.Text=“测试”或类似 private void textNazwa_TextChanged(object sender, EventArgs e) { changesToClient = true; } 如何使事件只在用户交互时触发而不在代码更改时触发?好吧,

我有一个简单的
文本框,开头是空的。我有一个简单的事件_TextChanged,用来知道用户何时更改了
文本框中的任何内容。但是,如果我自己从代码中对事件执行任何操作,就会触发该事件。如设置
textbox.Text=“测试”或类似

    private void textNazwa_TextChanged(object sender, EventArgs e) {
        changesToClient = true;
    }

如何使事件只在用户交互时触发而不在代码更改时触发?

好吧,无论如何,你也不能。您可以做的是在进行更改之前删除处理程序,并在进行更改之后将其添加回

e、 g


如果您的方法的作用域与您更改文本框值的作用域与
textNazwa_TextChanged
(例如,两者都在一个表单中)相同,您可以设置一个标志,或者如果这对您来说不够糟糕,您可以使用责任链来确定是否应调用
textNazwa_TextChanged
方法

事件本身不区分通过用户输入输入的文本和通过代码更改的文本。您必须自己设置一个标志,告诉代码忽略该事件。比如说,

private bool ignoreTextChanged;

private void textNazwa_TextCanged(object sender, EventArgs e)
{
    if (ignoreTextChanged) return;
}
然后使用它来设置文本,而不是只调用
text=“…”

从你对另一个答案的评论来看,听起来你有很多文本框。在这种情况下,可以通过以下方式修改函数:

private void SetTextBoxText(TextBox box, string text)
{
    ignoreTextChanged = true;

    box.Text = text;

    ignoreTextChanged = false;
}
那么就这样称呼它:

SetTextBoxText(textNazwa, "foo");

这将完成与只执行
textNazwa.Text=“foo”
相同的操作,但将设置标志,让事件处理程序知道忽略事件。

我建议您对具有属性的演示者使用文本框绑定,因此如果您需要更改代码中的值(例如用于测试)您不需要触发事件或更改UI代码。您需要做的唯一一件事就是为演示者设置一个值

public class Presenter : INotifyPropertyChanged
{
    public string MyTextValue { get; set; }
    public event PropertyChangedEventHandler PropertyChanged;
    /// Create a method here that raises the event that you call from your setters..
}
然后在Windows窗体代码中,需要为演示者设置bindingSource,并向文本框添加绑定:

编辑

private BindingSource myPresenterSource ;
this.myPresenterSource = new System.Windows.Forms.BindingSource(this.components);
// Some time later in the

((System.ComponentModel.ISupportInitialize)(this.myPresenterSource )).BeginInit();
// you set the DataSource of your BindingSource
// m_SettingsBindingSource
//
this.myPresenterSource .DataSource = typeof(Presenter );

// and when you create your TextBox you do this :
this.YourTextBox.DataBindings.Add(new System.Windows.Forms.Binding("Text",
   this.myPresenterSource, "MyTextValue", true,
   System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
然后在InitializeComponent中,将源设置为:

myPresenterSource.DataSource = new Presenter();

查看更多资源,了解如何在Windows窗体中实现(MVP)。

我一直在使用这个过程,它似乎工作得很好。如果事件触发且焦点不在文本框中,则我忽略该请求,因此当我设置文本时,焦点在其他位置,但当用户在文本框中键入时,它具有焦点,因此我确认更改

private void textNazwa_TextCanged(object sender, EventArgs e)
{
    if ( !textNazwa.Focused) 
        return; 
}

对我来说,我会这样做

bool wasUserTyping = false;
private void textNazwa_KeyUp(object sender, KeyEventArgs e){
     wasUserTyping = true;
}

private void textNazwa_TextChanged(object sender, TextChangedEventArgs e){
    if(wasUserTyping){
          //Yaaay!! User did type
    }
}

你不能,它没有区别。解决方法可能是在手动编辑文本之前取消订阅,但这是最糟糕的。如果你的事件无限地相互调用,你应该在设计中更改其他内容。打破事件之间的依赖循环,或添加停止条件。(例如,对于TextChanged事件,当新文本与旧文本相同时,事件不应被触发。)@Ineradial:这种事情很常见;控件本身并不能确保文本实际上已经更改,只是设置了属性本身。因此,如果我有30多个文本框,几个带有_TextChanged的复选框,我所能做的就是逐个禁用它们。。。然后启用..或设置标志或使用责任链这实际上比禁用/启用事件更好;那么假就足够了。当然,如果你能展示一个,那就太好了。我正在尝试学习Entity Framework来填充WinForm,然后在用户按下Save后将更改保存回数据库。因此,您可以使用EntityFramework作为模型,然后使用Presenter将其包装,并按照我所述将Presenter设置为BindingSource。您应该需要“手动”更改UI元素的值哇,这非常巧妙。当然,可能会出现一些罕见的情况,即用户碰巧同时使用控件时,由计时器触发绑定更新,但从一开始,这将是一个糟糕的设计。对于我的用例来说,这个解决方案是最好的。我也喜欢这个。我猜它会对复选框起作用,这在此刻对我来说是一个真正的痛苦(textNazwa专注于此)。如果文本框在通过代码更改时处于焦点状态,则此示例将失败。
if(textNazwa.focused){//Do something}
wrapping-code-like仅在用户实际手动更改时才会运行。请解释此代码解决问题的原因以及此设计的权衡。
private void textNazwa_TextCanged(object sender, EventArgs e)
{
    if ( !textNazwa.Focused) 
        return; 
}
bool wasUserTyping = false;
private void textNazwa_KeyUp(object sender, KeyEventArgs e){
     wasUserTyping = true;
}

private void textNazwa_TextChanged(object sender, TextChangedEventArgs e){
    if(wasUserTyping){
          //Yaaay!! User did type
    }
}