c# - 事件循环

标签 c# winforms user-interface circular-reference

我发现自己经常遇到以下情况:

我有一个绑定(bind)到某些数据的用户控件。每当更新控件时,基础数据也会更新。每当基础数据更新时,控件也会更新。因此很容易陷入永无止境的更新循环(控制更新数据、数据更新控制、控制更新数据等)。

通常我通过使用 bool 值(例如 updatedByUser)来解决这个问题,这样我就可以知道控件是通过编程方式更新了还是由用户更新了,然后我可以决定是否触发该事件更新基础数据。这看起来不太整洁。

是否有一些处理此类情况的最佳实践?

编辑:我添加了以下代码示例,但我想我已经回答了我自己的问题...?

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

最佳答案

一种选择是停止更新,以防数据自上次以来没有发生变化。例如,如果数据是类的形式,您可以检查数据是否与上次触发事件时的实例相同,如果是,则停止传播。

这是许多 MVVM 框架所做的,以防止在属性实际上没有更改的情况下引发 PropertyChanged 事件:

private string _someProperty = "";
public string SomeProperty
{
    get
    {
        return _someProperty;
    }
    set
    {
        if ( _someProperty != value )
        {
           _someProperty = value;
           RaisePropertyChanged();
        }
    }
}

您可以类似地为 Windows 窗体实现此概念。

关于c# - 事件循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38564979/

相关文章:

c# - 可以使用 Dapper 流式传输大型 SQL Server 数据库结果集吗?

c# - 如何使一个方法采用两种不同的类型

c# - 如何使用 Serilog 读取写入 Azure 表存储的日志?

c# - 如何将 VS2003 类自动转换为部分 Designer.cs 文件?

vb.net - 填写具有多个数据字段的表单的正确方法是什么?

c# - 当绑定(bind)源正确时,DataGridView 在 C# 中不更新

Python PyQT4 简单数据库 GUI

c# - 如何判断一个字节数组是否被压缩

mobile - 为什么HTML/Web UI响应比 native UI慢?

Matlab 图形用户界面 : How to update handles structure?