Как получить привязываемые свойства UserControl, которые работают с OnPropertyChanged - PullRequest
10 голосов
/ 06 июля 2011

У меня есть простой пользовательский контроль (WinForms) с некоторыми общедоступными свойствами. Когда я использую этот элемент управления, я хочу привязать данные к этим свойствам с DataSourceUpdateMode, установленным в OnPropertyChanged . Источником данных является класс, который реализует INotifyPropertyChanged.

Я осознаю необходимость создания привязок к свойствам, и я делаю это.

Я предполагал, что в моем пользовательском контроле должен быть реализован интерфейс, или свойства должны быть украшены каким-либо атрибутом или чем-то в этом роде. Но мое исследование оказалось пустым.

Как это сделать? В настоящий момент я делаю это, вызывая OnValidating () в моем usercontrol всякий раз, когда свойство изменяется, но это кажется неправильным.

Я могу получить подтверждение, если я установлю для CausesValidation значение true в usercontrol, но это не очень полезно для меня. Мне нужно проверить каждое дочернее свойство по мере его изменения.

Обратите внимание, что это WinForms ситуация.

РЕДАКТИРОВАТЬ: Очевидно, у меня нет таланта для объяснения, так что, надеюсь, это прояснит, что я делаю. Это сокращенный пример:

// I have a user control
public class MyControl : UserControl
{
    // I'm binding to this property
    public string ControlProperty { get; set; }

    public void DoSomething()
    {
        // when the property value changes, the change should immediately be applied 
        // to the bound datasource
        ControlProperty = "new value";

        // This is how I make it work, but it seems wrong
        OnValidating();         
    }
}

// the class being bound to the usercontrol
public class MyDataSource : INotifyPropertyChanged
{
    private string sourceProperty;
    public string SourceProperty
    {
        get { return sourceProperty; }
        set
        {
            if (value != sourceProperty)
            {
                sourceProperty = value;
                NotifyPropertyChanged("SourceProperty");
            }
        }
    }

    // boilerplate stuff
    public event PropertyChangedEventHandler PropertyChanged;
    protected void NotifyPropertyChanged(string info)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(info));
    }
}

public class MyForm : Form
{
    private MyControl myControl;
    public MyForm()
    {
        // create the datasource 
        var dataSource = new MyDataSource() { SourceProperty = "test" };

        // bind a property of the datasource to a property of the usercontrol
        myControl.DataBindings.Add("ControlProperty", dataSource, "SourceProperty",
            false, DataSourceUpdateMode.OnPropertyChanged); // note the update mode
    }
}

(я пробовал это с использованием BindingSource, но результат был тот же.)

Теперь я хочу, чтобы при изменении значения MyControl.ControlProperty это изменение немедленно распространялось на источник данных (экземпляр MyDataSource). Для этого я вызываю OnValidating () в usercontrol после изменения свойства. Если я этого не сделаю, мне придется подождать, пока проверка не будет вызвана изменением фокуса, которое является эквивалентом режима обновления «OnValidation», а не желаемого режима проверки «OnPropertyUpdate». Мне просто не хочется вызывать OnValidating () после изменения значения свойства, это правильно, даже если оно (вроде) работает.

Прав ли я, предполагая, что вызов OnValidating () не является правильным способом сделать это? Если да, то как мне уведомить источник данных об изменении ControlProperty?

Ответы [ 2 ]

14 голосов
/ 06 июля 2011

Я думаю, я понял это.Я не понял, как уведомления об изменениях отправлялись из элемента управления в связанный источник данных.

Да, вызов OnValidating () является неправильным способом.

Из того, что я собрал, есть дваспособы, которыми элемент управления может уведомить источник данных об изменении свойства.

Один из способов заключается в том, что элемент управления реализует INotifyPropertyChanged.Я никогда не делал этого со стороны контроля прежде, и я думал, что только сторона источника данных привязки должна была реализовать это.

Когда я реализовал INotifyPropertyChanged на своем пользовательском элементе управления и вызвал событие PropertyChanged в соответствующее время, это сработало.

Второй способ заключается в том, что элемент управления вызывает конкретное событие изменения для каждого свойства,Событие должно соответствовать соглашению об именах: <propertyname>Changed

например, для моего примера это будет

public event EventHandler ControlPropertyChanged

Если бы мое свойство называлось Foo, оно было бы FooChanged.

Мне не удалось заметить относительную часть документации MSDN , где говорится:

Чтобы уведомление об изменении происходило в привязке между связанным клиентом иДля источника данных тип привязки должен:

Реализовать интерфейс INotifyPropertyChanged (предпочтительно).

Предоставить событие изменения для каждого свойства связанного типа.

Этот второй способ заключается в том, как работают все существующие элементы управления WinForms, поэтому я делаю это сейчас.Я использую INotifyPropertyChanged в своем источнике данных, но я поднимаю события Changed на своем элементе управления.Это похоже на обычный способ.

1 голос
/ 06 июля 2011

Реализация интерфейса INotifyPropertyChanged очень проста. Вот пример, который показывает объект с одним открытым полем ...

public class Demo : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(info));
    }

    private string _demoField;

    public string DemoField
    {
        get {return demoField; }

        set
        {
            if (value != demoField)
            {
                demoField = value;
                NotifyPropertyChanged("DemoField");
            }
        }
    }
}

Затем вы должны создать экземпляр Binding для привязки свойства элемента управления к свойству (DemoField) в вашем исходном экземпляре (экземпляр Demo).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...