traveller
traveller

Reputation: 189

Two way databinding in winforms, Inotifypropertychanged implemented in base class

I use Winforms Databinding and I have derived classes, where the base class implements IPropertychanged :

    public event PropertyChangedEventHandler PropertyChanged;

    private void RaisePropertyChanged(string propertyName) {
        var handler = this.PropertyChanged;
        if (handler != null) {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

Each propertysetter calls:

    protected void SetField<T>(ref T field, T value, string propertyName) {
        if (!EqualityComparer<T>.Default.Equals(field, value)) {
            field = value;
            IsDirty = true;
            this.RaisePropertyChanged(propertyName);
        }
    }

A typical Propertysetter:

    public String LocalizationItemId {
        get {
            return _localizationItemId;
        }
        set {
             SetField(ref _localizationItemId, value, "LocalizationItemId");
        }
    }

The way a property is bound to a textbox

        private DerivedEntity derivedEntity
        TextBoxDerivedEntity.DataBindings.Add("Text", derivedEntity, "Probenname");

If I programmatically assign text to the textbox, the textbox does not show it. But I can manually edit the textbox.

Upvotes: 8

Views: 19203

Answers (4)

Cristian Oprea
Cristian Oprea

Reputation: 71

I implemented the "INotifyPropertyChanged", but raise the PropertyChanged event only when the new value is different from the old value:

public class ProfileModel : INotifyPropertyChanged
{
    private Guid _iD;
    private string _name;
    public event PropertyChangedEventHandler PropertyChanged;

    public Guid ID
    {
        get => _iD;
        set
        {
            if (_iD != value)
            {
                _iD = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("ID"));
            }
        }
    }

    public string Name
    {
        get => _name;
        set
        {
            if (_name != value)
            {
                _name = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Name"));
            }
        }
    }
}

Now just bind to the controls:

txtProfileID.DataBindings.Clear();
txtProfileID.DataBindings.Add("Text", boundProfile, "ID", true, DataSourceUpdateMode.OnPropertyChanged);

Upvotes: 1

SohoNYC75
SohoNYC75

Reputation: 21

The subscriber isn't initialized. i.e.

private DerivedEntity derivedEntity
TextBoxDerivedEntity.DataBindings.Add("Text", derivedEntity, "Probenname");

derivedEntity is null.

Initialize it and you'll be fine.

Upvotes: 1

Haider Ali
Haider Ali

Reputation: 2795

I know it is too late to answer, but this problem can be solved, if you set event when your binding should change value, if you set it on property value change event your problem will be solved. You can do this by this way

textBox.DataBindings.Add("textBoxProperty", entity, "entityProperty", true, DataSourceUpdateMode.OnPropertyChanged);

Upvotes: 14

Ryogo
Ryogo

Reputation: 101

Binding source is updated on TextBox Validated event. TextBox validated event is called when user edit TextBox and then changes focus to other control. Since you're changing TextBox text programmatically TextBox doesn't know that text were changed and therefore validation is not called and binding is not updated, so you need to update binding manually.

Initialize binding:

var entity;
textBox.DataBindings.Add("textBoxProperty", entity, "entityProperty");

Change TextBox.Text:

textBox.Text = "SOME_VALUE";

Update binding manually:

textBox.DataBindings["textBoxProperty"].WriteValue();

Binding.WriteValue() reads value from control and updates entity accordingly. You could read about WriteValue at MSDN.

Upvotes: 9

Related Questions