在我的程序中,当我的其他 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 。您最好让
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 应该像这样绑定(bind):
<ContentPresenter IsEnabled="{Binding Path=LeftWidgetEnabled}" />
而
DataContext
的 UserControl
(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/