在我的程序中,当我的其他 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; 成功更改了主窗口 View 模型中的属性,但 View 不受影响。我可以通过找到一种调用 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"); }
}

最佳答案

你的 LeftWidgetEnabled 类的 ViewModel.MainViewModel 必须是这样的:

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 应该像这样绑定(bind):
<ContentPresenter IsEnabled="{Binding Path=LeftWidgetEnabled}" />

DataContextUserControl (ContentPresenter 所在的位置)应该是 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>

关于c# - 我需要在代码隐藏中调用 INotifyPropertyChanged() 吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19791700/

10-13 07:45