Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Control not immediately updating bound property with INotifyPropertyChanged

I have controls which are not updating their bound object's respective properties until focus is lost. There are similar questions with accepted answers referencing DataSourceUpdateMode.OnPropertyChange being declared, which I do, yet the behavior persists. Here's an example implementation. I'll try to be thorough, yet concise. The MyConfig class is accessed through a property in a Singleton class I call Configuration.

[Serializable]
public class MyConfig : INotifyPropertyChanged
{
    public enum MyEnum
    {
        Foo,
        Bar
    }

    public MyConfig()
    {
        MyProperty = MyEnum.Foo;
    }

    private MyEnum _MyProperty;
    public MyEnum MyProperty
    {
        get { return _MyProperty; }
        set { if (value != _MyProperty) { _MyProperty = value; OnPropertyChanged("MyProperty"); } }
    }

    [field: NonSerialized]
    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string propertyName)
    {
        if (string.IsNullOrEmpty(propertyName))
            throw new ArgumentNullException(propertyName);
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

public partial class ConfigForm : Form
{
    public ConfigForm()
    {
        InitializeComponent();
        MyComboBox.Items.AddRange(Enum.GetNames(typeof(MyConfig.MyEnum)));
    }

    private void ConfigForm_Load(object sender, EventArgs e)
    {
        MyComboBox.DataSource = Enum.GetValues(typeof(MyConfig.MyEnum));
        MyComboBox.DataBindings.Add("SelectedItem", Configuration.Instance.MyConfig, "MyProperty", false, DataSourceUpdateMode.OnPropertyChanged);
    }
}

I'm not sure, given the following brief implementation, what I could be overlooking to ensure immediate property changes. I can change, in this case from Foo to Bar in the ComboBox, but unless I remove focus from the ComboBox, nothing changes. Does anyone have any ideas?

like image 809
Josh Clayton Avatar asked Dec 05 '11 21:12

Josh Clayton


1 Answers

The WinForms ComboBox is wonky with regards to OnPropertyChanged. Here's some code from an old project that I used to get OnPropertyChanged working the way I expect for the SelectedItem property. This works for my specific instance, but I usually struggle to get this scenario working sometimes. Good luck!

/// <summary>
/// A modification of the standard <see cref="ComboBox"/> in which a data binding
/// on the SelectedItem property with the update mode set to DataSourceUpdateMode.OnPropertyChanged
/// actually updates when a selection is made in the combobox.
/// </summary>
public class BindableComboBox : ComboBox
{
    /// <summary>
    /// Raises the <see cref="E:System.Windows.Forms.ComboBox.SelectionChangeCommitted"/> event.
    /// </summary>
    /// <param name="e">An <see cref="T:System.EventArgs"/> that contains the event data.</param>
    protected override void OnSelectionChangeCommitted(EventArgs e)
    {
        base.OnSelectionChangeCommitted(e);

        var bindings = this.DataBindings
            .Cast<Binding>()
            .Where(x => 
                x.PropertyName == "SelectedItem" && 
                x.DataSourceUpdateMode == DataSourceUpdateMode.OnPropertyChanged);
        foreach (var binding in bindings)
        {
            // Force the binding to update from the new SelectedItem
            binding.WriteValue();

            // Force the Textbox to update from the binding
            binding.ReadValue();
        }
    }
}
like image 143
Nicholas Piasecki Avatar answered Oct 16 '22 19:10

Nicholas Piasecki