Как обновить производные свойства с помощью INotifyPropertyChanged

#c# #.net #binding

#c# #.net #привязка

Вопрос:

У меня есть несколько свойств в списке привязок для XtraTreeList (DevExress), где дочерний узел должен отображать свойство parentnode ‘e. У меня есть следующий код.

 public abstract class ClassBase : INotifyPropertyChanged
{
    protected static int initialId = 0;

    private int id;
    private int parentID;
    private string productName;
    private string productType;
    private string colorProductType;

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

    public int ID
    {
        get { return id; }
        set
        {
            if ( id == value )
                return;

            id = value;
            RaisePropertyChanged("ID");
        }
    }

    public int ParentID
    {
        get { return parentID; }
        set
        {
            if ( parentID == value )
                return;

            parentID = value;
            RaisePropertyChanged("ParentID");
        }
    }

    public string ProductName
    {
        get { return productName; }
        set
        {
            if ( productName == value )
                return;

            productName = value;
            RaisePropertyChanged("ProductName");
        }
    }

    public string ProductType
    {
        get { return productType; }
        set
        {
            if ( productType == value )
                return;

            productType = value;
            RaisePropertyChanged("ProductType");
            RaisePropertyChanged("ColorProductType");
        }
    }

    public string ColorProductType
    {
        get { return colorProductType ; }
        set
        {
            if (colorProductType == value)
                return;

            colorProductType = value;
            RaisePropertyChanged("ColorProductType");
        }
    }

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    #endregion
}`
  

Мое требование состоит в том, чтобы ColorProductType свойство изменялось при изменении ProductType свойства, в основном ProductType это свойство родительского узла и ColorProductType — дочернего. Итак, при изменении родительского свойства необходимо изменить дочернее. У меня оба этих свойства привязаны к двум текстовым полям. Таким образом, изменение родительского реквизита должно изменить оба текстовых поля, но обратное неверно. RaisePropertyChanged("ColorProductType"); внутри родительского элемента не работает, colorproducttype равно null, в чем здесь проблема?

Ответ №1:

RaisePropertyChanged на самом деле свойство не обновляется. Это просто сигнализирует о PropertyChanged событии. Что-то где-то должно подписаться на это и соответствующим образом обновить другое свойство. Что-то вроде этого:

 public abstract class ClassBase : INotifyPropertyChanged
{
    private string productType;
    private string colorProductType;

    public ClassBase()
    {
        this.PropertyChanged  = HandlePropertyChanged;
    }

    private void HandlePropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if(e.PropertyName == "ProductType")
        {
            // update ColorProductType here
        }
    }

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

    public string ProductType
    {
        get { return productType; }
        set
        {
            if ( productType == value )
                return;

            productType = value;
            RaisePropertyChanged("ProductType");
        }
    }

    public string ColorProductType
    {
        get { return colorProductType ; }
        set
        {
            if (colorProductType == value)
                return;

            colorProductType = value;
            RaisePropertyChanged("ColorProductType");
        }
    }

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    #endregion
}
  

Естественно, это полный перебор. Вы можете обновлять ColorProductType при ProductType обновлении и позволить PropertyChanged событию и привязке данных обрабатывать обновление текстового поля:

 public string ProductType
{
    get { return productType; }
    set
    {
        if ( productType == value )
            return;

        productType = value;

        // update ColorProductType here

        RaisePropertyChanged("ProductType");
    }
}
  

Комментарии:

1. спасибо за ваши комментарии, возможно, мне придется использовать излишний подход, потому что в моем случае пользователь может редактировать colorproducttype, и в этом случае должно быть отдельное свойство для настройки colorprodtype . Но когда пользователь обновляет Producttype (родительский prop), он должен перезаписать дочернее свойство. Вы предлагаете мне сохранить свойство colorprodtype и по-прежнему обновлять colorproducttype в Producttype?

2. @WittyWoman Да. Я думаю, что второй пример кода, который я опубликовал, должен работать достаточно хорошо для вас. Я опустил ColorProductType это, но вы должны сохранить это в своем реальном коде. Затем, когда пользователь обновит ColorProductType , он будет работать так, как ожидалось, и когда пользователь обновится ProductType , код в установщике также будет сброшен ColorProductType . Если вы хотите, чтобы все было более разделено, вы могли бы использовать подход к обработке событий, который я опубликовал выше, и избежать побочного эффекта изменения ColorProductType в вашем ProductType установщике.

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