C# 带嵌入类的冒泡NotifyPropertyChange
所以这里有一个问题让我绕圈子。我正在使用一个嵌入式类结构,它需要保持其子对象的私有性,但应该能够从这些子对象中的数据向上传递某些NotifyOfPropertyChange事件。最好的方法是什么 我当前的方法是下面的代码,其中我的SystemViewModel视图(SystemView)有一个绑定到C# 带嵌入类的冒泡NotifyPropertyChange,c#,wpf,mvvm,caliburn.micro,C#,Wpf,Mvvm,Caliburn.micro,所以这里有一个问题让我绕圈子。我正在使用一个嵌入式类结构,它需要保持其子对象的私有性,但应该能够从这些子对象中的数据向上传递某些NotifyOfPropertyChange事件。最好的方法是什么 我当前的方法是下面的代码,其中我的SystemViewModel视图(SystemView)有一个绑定到CommunicationStatus属性的元素,我有一个父类SystemViewModel,它有一个子类CommunicationManager,它有子类Communicator,如下所示 困难的事
CommunicationStatus
属性的元素,我有一个父类SystemViewModel,它有一个子类CommunicationManager,它有子类Communicator,如下所示
困难的事情:
1) 在这种情况下,必须假设通信器没有系统视图模型的可见性,因此在通信器的Connected
属性的set
方法中放置NotifyOfPropertyChanged(()=>CommunicationStatus)
。。。除非我遗漏了一些明显的东西
2) SystemViewModel不能直接访问Communicator,因此无法从SystemView.xaml
绑定到连接的Connected
在我看来,Connected
中的NotifyOfPropertyChanged事件应该会出现在父类中,因为在所有类中都实现了PropertyChangedBase
,但这并没有发生。我愿意帮忙
public class SystemViewModel : PropertyChangedBase
{
private CommunicationManager CommunicationManager;
public string CommunicationStatus
{
get
{
if (CommunicationManager.YepConnected)
{
return "Green";
}
else
{
return "Red";
}
}
}
}
public class CommunicationManager : PropertyChangedBase
{
private Communicator Communicator;
public bool YepConnected { get { return Communicator.Connected; } }
}
public class Communicator: PropertyChangedBase
{
private bool _connected;
public bool Connected
{
get { return _connected; }
set
{
_connected = value;
NotifyOfPropertyChange(() => Connected);
}
}
}
编辑
因此,它似乎工作正常,并按预期将事件从子类传播到父类。真正的问题是WPF绑定与属性之间的关系,这一点更为隐蔽。仅供参考,我使用的XAML如下所示:
<TextBlock Text="Status" Background="{Binding CommunicationStatus}"/>
是的,如果你做得不完美,那就是即时堆栈溢出(双关语:)
每当Connected
的值改变时,我观察到CommunicationStatus
的get
方法就会执行。通过这样做,该执行将导致另一次执行get
方法,只是这次XAML会更新
有人能解释为什么这个解决方案有效和/或提供一个更雄辩的解决方案吗?下面是一个如何使用ReactiveUI实现这一点的示例
public class SystemViewModel : ReactiveObject
{
private readonly CommunicationManager communicationManager;
private readonly ObservableAsPropertyHelper<string> connectionStatus;
public SystemViewModel( CommunicationManager communicationManager )
{
this.communicationManager = communicationManager ?? throw new ArgumentNullException(nameof(communicationManager));
this.communicationManager
.WhenAnyValue( e => e.YepConnected, state => state ? "Green" : "Red" )
.ToProperty( this, e => e.ConnectionStatus, out connectionStatus );
}
public string ConnectionStatus => connectionStatus.Value;
}
简单测试
var communicator = new Communicator();
var manager = new CommunicationManager(communicator);
var vm = new SystemViewModel( manager );
vm.PropertyChanged += (s,e) => Console.WriteLine( "SystemViewModel.{0} changed", e.PropertyName );
communicator.Connected = true;
communicator.Connected = false;
生成输出
SystemViewModel.ConnectionStatus changed
SystemViewModel.ConnectionStatus changed
SystemViewModel.ConnectionStatus已更改
SystemViewModel.ConnectionStatus已更改
这是一个基本的类OO理论——简单地包装或隐藏属性。因此,您捕获来自成员实例的通知,并且只传递(传播)您特别允许的通知。我想我的问题是包装机制以及通知如何传播。如果我在
get
方法中包装一个成员实例的属性,那么它的通知是否仅仅因为在包装器中而在包装器中自动发出?或者更确切地说,如果我的get是ParentMethod{get{Child.A*Child.B*Child.C}
,那么从A
、B
、C
引发的通知是否会导致在ParentMethod
中引发通知?这个问题的答案是肯定的。这个问题更为复杂。请参阅更新的编辑
public class Communicator : ReactiveObject
{
private bool _connected;
public bool Connected
{
get { return _connected; }
set { this.RaiseAndSetIfChanged( ref _connected, value); }
}
}
var communicator = new Communicator();
var manager = new CommunicationManager(communicator);
var vm = new SystemViewModel( manager );
vm.PropertyChanged += (s,e) => Console.WriteLine( "SystemViewModel.{0} changed", e.PropertyName );
communicator.Connected = true;
communicator.Connected = false;
SystemViewModel.ConnectionStatus changed
SystemViewModel.ConnectionStatus changed