控制值更改后,为什么绑定项不会更新?

时间:2015-06-09 23:20:39

标签: c# winforms data-binding

我很难绑定属性。我可能在这里遗漏了一些东西。问题是我的对象属性不会被界面控件更改更新,直到我与UI进行另一次交互,比如按空虚拟按钮。这真的很奇怪。我在这里缺少什么?如何在控制检查更改时更新bind属性?

样品:

  • 创建一个空表单,添加一个CheckBox和一个按钮。
  • 将复选框绑定到IsOnSale Car属性。
  • 添加一个控制台写信线,以查看何时更改IsOnSale属性。
  • 构建并单击Checkbox,IsOnSale不会更改(没有控制台消息),直到单击另一个按钮或其他内容。
  • 点击虚拟按钮,IsOnSale属性将被更改!什么!??

    private Car car;
    
    public Form1()
    {
        InitializeComponent();
    
        car = new Car();
        car.IsOnSale = false;
    
        checkBox1.DataBindings.Add("Checked", car, "IsOnSale");
    }
    
    //U dont need this for the test..
    private void btnPrintStatus_Click(object sender, EventArgs e)
    {
        string s = car.ToString();
        Console.WriteLine(s);
    }
    

Car只是一个实现INotifyPropertyChanged的类。此外,每次发生属性更改请求时,它都会在控制台上打印(仅用于调试)。正如您所看到的那样,如果您构建示例,则仅在单击虚拟按钮后才会发出更改请求...

internal class Car : INotifyPropertyChanged, INotifyPropertyChanging
{
    private string name;

    public string Name
    {
        get { return name; }
        set
        {
            string propName = GetName(new { Name });
            UpdateField(ref name, value, propName, null);
        }
    }
    private bool isOnSale;

    public bool IsOnSale
    {
        get { return isOnSale; }
        set
        {
            string propName = GetName(new { IsOnSale });
            UpdateField(ref isOnSale, value, propName, null);
        }
    }

    public override string ToString()
    {
        return string.Format("Car Name: {0}. IsOnSale: {1}", Name, IsOnSale);
    }

    #region  INotifyPropertyChanged, INotifyPropertyChanging
    public event PropertyChangingEventHandler PropertyChanging;
    public event PropertyChangedEventHandler PropertyChanged;

    public static string GetName<T>(T item) where T : class
    {
        return typeof(T).GetProperties()[0].Name;
    }

    protected bool UpdateField<T>(ref T field, T newValue, string propertyName, Action action = null)
    {
        bool needChange = !EqualityComparer<T>.Default.Equals(field, newValue);
        Console.WriteLine("Try to UpdateField {0}. Need update? {1}", propertyName, needChange);

        if (needChange)
        {
            OnPropertyChanging(propertyName);
            field = newValue;
            if (action != null)
                action();
            OnPropertyChanged(propertyName);
        }
        return needChange;
    }

    protected void OnPropertyChanging(string propertyName)
    {
        PropertyChangingEventHandler handler = PropertyChanging;
        if (handler != null)
            handler(this, new PropertyChangingEventArgs(propertyName));
    }

    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName));
    }
    #endregion
}

编辑 - 解决方法

我能够找到一种解决方法,但它闻起来...... 我正在使用BackgroundWorker“退出”更改事件,之后我点击了一个虚拟按钮。

    private void checkBox1_CheckedChanged(object sender, EventArgs e)
    {
        //Wont work, need to get out of this event.
        //btnDummy.PerformClick();

        //Using another thread to get out of this event:
        RunAsyncBindFixer();
    }

    private void RunAsyncBindFixer()
    {
        var workerBindFixer = new BackgroundWorker();
        workerBindFixer.DoWork += WorkerBindFixer_DoWork;
        workerBindFixer.RunWorkerCompleted += WorkerBindFixer_RunWorkerCompleted;
        Console.WriteLine("Starting RunAsyncBindFixer");
        workerBindFixer.RunWorkerAsync();
    }

    void WorkerBindFixer_DoWork(object sender, DoWorkEventArgs e)
    {
        //Aparently we need nothing here.
        //Thread.Sleep(0);
    }

    void WorkerBindFixer_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        Console.WriteLine("RunAsyncBindFixer RunWorkerCompleted");
        btnDummy.PerformClick();
        //Checked change on a dummy checkbox wont work also
        //ckbDummy.Checked = !ckbDummy.Checked;
        Console.WriteLine("Dummy action applied");
    }

1 个答案:

答案 0 :(得分:3)

数据绑定默认为每当验证绑定控件时写入值,这通常在控件失去焦点时发生(例如按下按钮时如图所示)

您可以强制数据绑定使用控件支持的控件的onpropertychanged(在这种情况下CheckedChanged,复选框控件支持)

checkBox1.DataBindings.Add("Checked", car, "IsOnSale", true, DataSourceUpdateMode.OnPropertyChanged);