OnPropertyChanged用于嵌套属性

时间:2015-03-29 04:34:38

标签: c# wpf

我将以下课程作为DataContext的{​​{1}}:

UserControl

我将public class ModelBase<T> : INotifyPropertyChanged where T : class { public T Model { get; set; } public void UpdateUI() { OnPropertyChanged(string.Empty); } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); } } 设置为包含基本类型的任意类。 我似乎正确地完成了绑定,因为我可以看到在UI中更改属性时正在填充属性。 但问题是,当我从后面的代码更改属性时,即使在调用Model之后,它也不会使用它来更新视图。我验证了UI的UpdateUI()中的属性(使用WPF / XAML检查软件),它们具有正确的值。

我认为它与DataContext中的嵌套类这一事实有关,因为我尝试向DataContext添加属性来测试它,并且绑定工作正常我打电话给ModelBase

我正在创建控件/绑定并将其添加到后面代码中的UpdateUI(),我不确定这是否会导致问题:

UserControl

1 个答案:

答案 0 :(得分:1)

TwoWay绑定,您必须具备以下条件:

  • 支持字段

  • setter引发属性更改的公共属性 通知。

  • 实现INotifyPropertyChanged接口或继承的模型 来自实现它的类

这是一个很好的方法:

重写您的ModelBase(基于Implementing INotifyPropertyChanged - does a better way exist?):

public class ModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

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


     protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
        {
            //make sure we fire the event only when newvalue!=oldvalue
            if (EqualityComparer<T>.Default.Equals(field, value)) return false;
            field = value;
            OnPropertyChanged(propertyName);
            return true;
        }
}

并将其用作

class Model:ModelBase{
   //example for a property that is appropriate for 2 way bidning
   private string _prop;
   public string prop{
      get{return _prop;}
      set{SetField(ref _prop,value);}
   }
}

如果这还不够,请解释原因。

更新:根据您的需要,您几乎可以按照自己的方式进行操作,但只是您没有正确指定PropertyPath,它应该是"Model."+nameOfProperty并注意到您除非您的容器Source = myModelBase未设置为DataContext,否则不需要设置var binding = new Binding { Path = new PropertyPath("Model."+nameOfProperty), Mode = BindingMode.Default, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged };

所以:

var binding = new Binding
                {
                    Source = myModelBase,
                    Path = new PropertyPath("Model."+nameOfProperty),
                    Mode = BindingMode.Default,
                    UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
                };

或者:

{{1}}

不确定这是否有效,但可能是问题,否则你的想法很好。