4 votes

Circularité des événements

Je me retrouve assez souvent dans la situation suivante :

J'ai un contrôle utilisateur qui est lié à certaines données. Chaque fois que le contrôle est mis à jour, les données sous-jacentes sont mises à jour. Chaque fois que les données sous-jacentes sont mises à jour, le contrôle est mis à jour. Il est donc assez facile de se retrouver coincé dans une boucle sans fin de mises à jour (le contrôle met à jour les données, les données mettent à jour le contrôle, le contrôle met à jour les données, etc.)

En général, je contourne ce problème en utilisant un bool (par exemple, le mot "bool"). updatedByUser ) pour savoir si un contrôle a été mis à jour par programme ou par l'utilisateur. Je peux alors décider de déclencher ou non l'événement pour mettre à jour les données sous-jacentes. Cela ne semble pas très net.

Existe-t-il des pratiques exemplaires pour faire face à de tels scénarios ?

EDIT : J'ai ajouté l'exemple de code suivant, mais je pense avoir répondu à ma propre question... ?

public partial class View : UserControl
{
    private Model model = new Model();

    public View()
    {
        InitializeComponent();
    }

    public event EventHandler<Model> DataUpdated;

    public Model Model
    {
        get
        {
            return model;
        }
        set
        {
            if (value != null)
            {
                model = value;
                UpdateTextBoxes();
            }
        }
    }

    private void UpdateTextBoxes()
    {
        if (InvokeRequired)
        {
            Invoke(new Action(() => UpdateTextBoxes()));
        }
        else
        {
            textBox1.Text = model.Text1;
            textBox2.Text = model.Text2;
        }
    }

    private void textBox1_TextChanged(object sender, EventArgs e)
    {
        model.Text1 = ((TextBox)sender).Text;
        OnModelUpdated();
    }

    private void textBox2_TextChanged(object sender, EventArgs e)
    {
        model.Text2 = ((TextBox)sender).Text;
        OnModelUpdated();
    }

    private void OnModelUpdated()
    {
        DataUpdated?.Invoke(this, model);
    }
}

public class Model
{
    public string Text1 { get; set; }
    public string Text2 { get; set; }
}

public class Presenter
{
    private Model model;
    private View view;

    public Presenter(Model model, View view)
    {
        this.model = model;
        this.view = view;

        view.DataUpdated += View_DataUpdated;
    }

    public Model Model
    {
        get
        {
            return model;
        }
        set
        {
            model = value;
            view.Model = model;
        }
    }

    private void View_DataUpdated(object sender, Model e)
    {
        //This is fine.
        model = e;

        //This causes the circular dependency.
        Model = e;
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X