我是否需要在代码隐藏中调用NotifyPropertyChange()?

时间:2013-11-05 14:47:36

标签: c# wpf mvvm inotifypropertychanged

在我的计划中,当我的其他contentPresenter获得焦点时,我想停用contentPresenter。每个演示者都由位于我的MainWindowViewModel中的属性表示。这也是两位演示者IsEnabled属性所在的位置。

使用以下结构创建contentPresenters:UserControl - > ViewModel - >数据模型。

现在我尝试通过更改主窗口的ViewModel中的contentPresenter属性来禁用必需的IsEnabled,该contentPresenter属性来自获得焦点的contentPresenter的代码隐藏。

public partial class EditBlockUC : UserControl { public EditBlockViewModel ViewModel { get { return DataContext as EditBlockViewModel; } } public EditBlockUC() { InitializeComponent(); } //Runs when the user control gets focus private void UserControl_GotFocus(object sender, RoutedEventArgs e) { //This UserControl has access to MainWindowViewModel through //it's own ViewModel, EditBlockViewModel ViewModel.MainViewModel.LeftWidgetEnabled = false; } } 用户控制代码隐藏:

ViewModel.MainViewModel.LeftWidgetEnabled = false;

行:NotifyPropertyChange()成功更改了主窗口视图模型中的属性,但视图不受影响。我可以通过找到一种方式来调用public class PropertyChangedBase : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); } public virtual void NotifyPropertyChange<TProperty>(Expression<Func<TProperty>> property) { var lambda = (LambdaExpression)property; MemberExpression memberExpression; if (lambda.Body is UnaryExpression) { var unaryExpression = (UnaryExpression)lambda.Body; memberExpression = (MemberExpression)unaryExpression.Operand; } else memberExpression = (MemberExpression)lambda.Body; OnPropertyChanged(memberExpression.Member.Name); } protected bool SetField<T>(ref T field, T value, string propertyName) { if (EqualityComparer<T>.Default.Equals(field, value)) return false; field = value; OnPropertyChanged(propertyName); return true; } } 来解决这个问题吗?如果是这样,我该怎么做?

如果这是完全错误的解决方案,请告诉我,并帮我解决。

谢谢

更新1:

我完整的基类:

LeftWidgetEnabled

更新2:

我的public bool LeftWidgetEnabled { get { return _leftWidgetEnabled; } set { SetField(ref _leftWidgetEnabled, value, "LeftWidgetEnabled"); } } 财产:

{{1}}

2 个答案:

答案 0 :(得分:4)

LeftWidgetEnabled课程的ViewModel.MainViewModel必须如下:

private bool leftWidgetEnabled;
public bool LeftWidgetEnabled
{
    get { return leftWidgetEnabled; }
    set { SetField(ref leftWidgetEnabled, value, "LeftWidgetEnabled"); }
}

此外,您的MainViewModel必须实施INotifyPropertyChanged

最好让MainViewModel继承ViewModelBase并让ViewModelBase实施INotifyPropertyChanged

public class MainViewModel : ViewModelBase
{        
    private bool leftWidgetEnabled;
    public bool LeftWidgetEnabled
    {
        get { return leftWidgetEnabled; }
        set { SetField(ref leftWidgetEnabled, value, "LeftWidgetEnabled"); }
    }
}

public class ViewModelBase : INotifyPropertyChanged
{
    // boiler-plate
    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, string propertyName)
    {
        if (EqualityComparer<T>.Default.Equals(field, value)) return false;
        field = value;
        OnPropertyChanged(propertyName);
        return true;
    }
}

更新1

您的ContentPresenter应该绑定如下:

<ContentPresenter IsEnabled="{Binding Path=LeftWidgetEnabled}" />

DataContext的{​​{1}}(UserControl所在的位置)应该是ContentPresenter的实例。

例如:

MainViewModel

答案 1 :(得分:0)

您实现INotifyPropertyChanged如下

class ViewModel : INotifyPropertyChanged
{

  private bool leftWidgetEnabled;
  public bool LeftWidgetEnabled
  {
     get 
      { 
        return leftWidgetEnabled;
      }
      set 
      { 
          leftWidgetEnabled=value
         OnPropertyChanged("LeftWidgetEnabled"); 
      }
   }

    public void OnPropertyChanged(string PropertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}