C# 如何通知对象实例外部的属性?

C# 如何通知对象实例外部的属性?,c#,wpf,inotifypropertychanged,C#,Wpf,Inotifypropertychanged,我是WPF初学者,我对PropertyChanged事件有问题: 我有一个viewmodel,其中包含另一个viewmodel的实例。(我将在此处使用通用名称) 我希望AxisVM的实例通知我的SomeDouble属性。(不能使用转换器) 编辑:我没有在这里包含完整的类,PropertyChangedEvent显然已经实现了。 AxisVM也继承自INotifyPropertyChanged(我使用ClassMemberName) 在XAML中,我将Viewmodel绑定为DataContext

我是WPF初学者,我对
PropertyChanged
事件有问题:

我有一个viewmodel,其中包含另一个viewmodel的实例。(我将在此处使用通用名称)

我希望
AxisVM
的实例通知我的
SomeDouble
属性。(不能使用转换器)

编辑:我没有在这里包含完整的类,
PropertyChangedEvent
显然已经实现了。
AxisVM
也继承自
INotifyPropertyChanged
(我使用ClassMemberName)

在XAML中,我将Viewmodel绑定为DataContext(在本例中,我认为这无关紧要),然后将下限绑定到文本框

当我编辑文本框时,轴的下限事件被触发,值被更改(view和viewmodel),但我需要通知我的
SomeDouble
属性,因为它在下限更改时被更新

我的ViewModel中axis实例的property changed事件从未被激发,即使我访问了它的属性(它确实激发了它的事件,但没有通知我的
SomeDouble
属性)


我现在不知所措,非常感谢您的帮助。

当您在AxisVM中实现
INotifyPropertyChanged
时,您在那里添加了
PropertyChanged
事件。在
ViewModel
和fire
FireOnPropertyChanged()中处理它


您可以为此使用事件

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

    ...
}