Comment distinguer dans un événement C# si une modification a été faite à partir du code ou par l'utilisateur?

J'ai un simple TextBox qui est vide au début. J'ai un événement simple, _TextChanged, pour savoir quand l'Utilisateur a changé quelque chose dans ce TextBox. Cependant, l'événement se déclenche si je fais quelque chose avec moi-même à partir du code. Comme réglage textbox.Text = "Test"; ou similaire.

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

Comment faire en sorte que l'événement ne se déclenche que sur l'interaction de l'utilisateur et non sur les modifications de code?

26
demandé sur Peter Mortensen 2011-11-27 23:45:47

4 réponses

L'événement lui-même ne fait pas de distinction entre le texte entré via l'entrée de l'utilisateur et le texte modifié via le code. Vous devrez définir vous-même un drapeau qui indique à votre code d'ignorer l'événement. Par exemple,

private bool ignoreTextChanged;

private void textNazwa_TextCanged(object sender, EventArgs e)
{
    if (ignoreTextChanged) return;
}

Ensuite, utilisez ceci pour définir le texte au lieu d'appeler simplement Text = "...";:

private void SetTextboxText(string text)
{
    ignoreTextChanged = true;

    textNazwa.Text = text;

    ignoreTextChanged = false;
}

A en juger par votre commentaire à une autre réponse, il semble que vous ayez un certain nombre de zones de texte. Dans ce cas, vous pouvez modifier la fonction de cette façon:

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

    box.Text = text;

    ignoreTextChanged = false;
}

Alors appelez-le comme ce:

SetTextBoxText(textNazwa, "foo");

Cela accomplirait la même chose que de simplement faire textNazwa.Text = "foo", mais définira le drapeau permettant à votre gestionnaire d'événements d'ignorer l'événement.

19
répondu Adam Robinson 2011-11-27 19:50:28

J'ai utilisé ce processus, et il semble bien fonctionner. Si l'événement se déclenche et que le focus n'est pas dans la zone de texte, alors j'ignore la requête, donc quand je définis le texte, le focus est ailleurs, mais lorsque l'utilisateur tape dans la zone de texte, il a le focus, donc je reconnais les changements.

private void textNazwa_TextCanged(object sender, EventArgs e)
{
    if ( !textNazwa.Focused) 
        return; 
}
28
répondu rwg 2015-11-20 17:33:00

Eh bien, vous ne pouvez pas pas vraiment de toute façon. Ce que vous pouvez faire est de supprimer le Gestionnaire avant de faire votre modification et de l'ajouter après avoir effectué la modification.

Par exemple

  textNazwa.TextChanged -= textNazwa_TextChanged;
  textbox.Text = "Test";
  textNazwa.TextChanged += textNazwa_TextChanged;

Si votre méthode a la même portée que celle où vous modifiez la valeur de la zone de texte que textNazwa_TextChanged (par exemple, les deux sont dans un formulaire), vous pouvez définir un indicateur à la place ou si cela ne vous suffit pas, vous pouvez utiliser la chaîne de responsabilité pour déterminer si la méthode textNazwa_TextChanged doit être appelée

6
répondu Conrad Frix 2011-11-27 19:48:19

Je vous suggère d'utiliser des liaisons pour votre zone de texte avec un présentateur qui a des propriétés, donc si vous avez besoin de changer vos valeurs dans le code (pour tester par exemple), vous ne devez pas déclencher d'événements ou changer de code D'interface utilisateur. La seule chose que vous devez faire est de définir une valeur sur votre animateur.

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..
}

Et puis dans votre code Windows Forms, vous avez besoin d'un bindingSource défini sur votre présentateur, et ajoutez une liaison à vos zones de texte:

Modifier

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));

Ensuite, dans votre InitializeComponent vous définissez la source comme ceci :

myPresenterSource.DataSource = new Presenter();

Vérifiez plus de ressources en cherchant comment implémenter le Movel-View-Presenter (MVP) dans Windows Forms.

1
répondu MBen 2014-01-17 22:32:51