繁体   English   中英

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

[英]Do I need to call NotifyPropertyChange() in code-behind?

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

两个contentPresenters都使用以下结构创建:UserControl - > ViewModel - > Data Model。

现在我试图通过从获得焦点的contentPresenter的代码隐藏更改主窗口的ViewModel中的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()来解决这个问题吗? 如果是这样,我该怎么做?

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

谢谢

更新1:

我完整的基类:

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;
    }
}

更新2:

我的LeftWidgetEnabled属性:

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

ViewModel.MainViewModel类的LeftWidgetEnabled必须如下所示:

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

此外,您的MainViewModel必须实现INotifyPropertyChanged

你最好让MainViewModelViewModelBase继承,让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}" />

UserControlDataContextContentPresenter所在的位置)应该是MainViewModel一个实例。

例如:

<UserControl 
    x:Class="MyApplication.UserControl1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:viewModels="**PATH TO YOUR VIEWMODELS-ASSEMBLY**"
    mc:Ignorable="d">

<UserControl.DataContext>
    <viewModels:MainViewModel />
</UserControl.DataContext>

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

您实现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;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM