C# 如何通知对象实例外部的属性?
我是WPF初学者,我对C# 如何通知对象实例外部的属性?,c#,wpf,inotifypropertychanged,C#,Wpf,Inotifypropertychanged,我是WPF初学者,我对PropertyChanged事件有问题: 我有一个viewmodel,其中包含另一个viewmodel的实例。(我将在此处使用通用名称) 我希望AxisVM的实例通知我的SomeDouble属性。(不能使用转换器) 编辑:我没有在这里包含完整的类,PropertyChangedEvent显然已经实现了。 AxisVM也继承自INotifyPropertyChanged(我使用ClassMemberName) 在XAML中,我将Viewmodel绑定为DataContext
PropertyChanged
事件有问题:
我有一个viewmodel,其中包含另一个viewmodel的实例。(我将在此处使用通用名称)
我希望AxisVM
的实例通知我的SomeDouble
属性。(不能使用转换器)
编辑:我没有在这里包含完整的类,PropertyChangedEvent
显然已经实现了。
AxisVM
也继承自INotifyPropertyChanged
(我使用ClassMemberName)
在XAML中,我将Viewmodel绑定为DataContext(在本例中,我认为这无关紧要),然后将下限绑定到文本框
当我编辑文本框时,轴的下限事件被触发,值被更改(view和viewmodel),但我需要通知我的SomeDouble
属性,因为它在下限更改时被更新
我的ViewModel中axis实例的property changed事件从未被激发,即使我访问了它的属性(它确实激发了它的事件,但没有通知我的SomeDouble
属性)
我现在不知所措,非常感谢您的帮助。当您在AxisVM中实现
INotifyPropertyChanged
时,您在那里添加了PropertyChanged
事件。在ViewModel
和fireFireOnPropertyChanged()中处理它
您可以为此使用事件
在AxisVM中添加事件
public class AxisVM: INotifyPropertyChanged
{
public event EventHandler LowerLimitChanged;
private double lowerLimit;
public double LowerLimit
{
get { return lowerLimit };
set { lowerLimit = value; FireOnPropertyChanged(); LowerLimitChanged?.Invoke(this, EventArgs.Empty); }
}
}
然后像这样订阅
public class ViewModel : INotifyPropertyChanged
{
private AxisVM axis;
public ViewModel()
{
this.AxisVM = new AxisVM();
this.AxisVM.LowerLimitChanged += OnLowerLimitChanged;
}
public AxisVM Axis
{
get { return axis};
set { axis = value; FireOnPropertyChanged(); }
}
public double SomeDouble
{
get { return axis.Lowerlimit * 1.5 };
}
public void OnLowerLimitChanged(object sender, EventArgs e)
{
FireOnPropertyChanged("SomeDouble");
}
}
您可以删除FireOnPropertyChanged(“SomeDouble”)
在属性中公共AxisVM Axis
,因为只有在设置AxisVM实例时才会触发此命令,而在该实例中的属性发生更改时不会触发此命令。只需在视图模型中处理AxisVM
的PropertyChanged
:
public class ViewModel : INotifyPropertyChanged
{
private readonly AxisVM axis;
public ViewModel()
{
axis = new AxisVM();
axis.PropertyChanged += Axis_PropertyChanged;
}
private void Axis_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
FireOnPropertyChanged(nameof(SomeDouble));
}
...
}
请看一看,你可以使用事件。或者将两个Ui元素绑定到LowerLimit并使用转换器(仅当SomeDouble仅用于在Ui中显示时)。通常存在父/子关系。若家长需要了解孩子,那个么通常家长会订阅孩子事件。Public
Axis
setter是一个问题,您必须从以前的孩子那里取消订阅并订阅一个新的(或者您可能有内存泄漏)。同时,家长可能不得不在某个地方退订。您真的需要public
setter吗?为什么axisvm中没有somedouble,viewmodel中没有LowerLit?viewmodel的目的是使数据和过程适应视图。将这些属性放在单独的视图模型中似乎只会让事情变得更困难。因此,您所做的不是将相关属性放在一个或另一个vm中,而是创建一个依赖项。一个vm需要知道另一个vm中的属性。这是您应该避免的事情。我已经在AxisVm中触发了该事件。当Lowerlimit更改时,它会在UI中更新。我需要的是AxisVM的实例来通知我的SomeDouble属性。@d0neall:你看到我的答案了吗?您应该为事件处理程序中的SomeDouble
属性引发PropertyChanged
事件。抱歉。它可以工作,但我有几个实例,我不应该使用太多的事件。谢谢你是否没有更干净的方法来执行此操作
——只有我的意见,但要在MVVM Light lib中检查更干净的代码Messenger。允许您发布消息,而不必拥有publisher实例。再加上编写彼此不包含实例的小视图模型,可以得到相当好的代码。当您实现InotifyPropertyChanged时,PropertyChanged事件已经可用。不确定@walkerbox的意思是否相同,但您不需要LowerLimitChanged
事件。订阅PropertyChanged
并检查e.PropertyName
是nameof(LowerLimit)
或”
(用于告诉“所有属性都已更改”)。我已经这样做了,我会再做一次。消费者可能只对LowerLimit
的更改感兴趣。除了PropertyChanged之外,添加LowerLimitChanged
事件显然不是唯一的解决方案,但这是一个非常明智的解决方案。你可以做得太正交了。这很有效,谢谢,但是没有更干净的方法来做这件事吗?一种更干净的方法来连接事件处理程序并处理对象的事件?不,我不这么认为。您应该在Axis\u property changed
方法中检查属性名称,因为它将被每个属性触发,而不仅仅是LowerLimit
public class AxisVM: INotifyPropertyChanged
{
public event EventHandler LowerLimitChanged;
private double lowerLimit;
public double LowerLimit
{
get { return lowerLimit };
set { lowerLimit = value; FireOnPropertyChanged(); LowerLimitChanged?.Invoke(this, EventArgs.Empty); }
}
}
public class ViewModel : INotifyPropertyChanged
{
private AxisVM axis;
public ViewModel()
{
this.AxisVM = new AxisVM();
this.AxisVM.LowerLimitChanged += OnLowerLimitChanged;
}
public AxisVM Axis
{
get { return axis};
set { axis = value; FireOnPropertyChanged(); }
}
public double SomeDouble
{
get { return axis.Lowerlimit * 1.5 };
}
public void OnLowerLimitChanged(object sender, EventArgs e)
{
FireOnPropertyChanged("SomeDouble");
}
}
public class ViewModel : INotifyPropertyChanged
{
private readonly AxisVM axis;
public ViewModel()
{
axis = new AxisVM();
axis.PropertyChanged += Axis_PropertyChanged;
}
private void Axis_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
FireOnPropertyChanged(nameof(SomeDouble));
}
...
}