我目前正在尝试进入WPF和MVVM,但我最近遇到了一个我不知道如何解决的问题。我是新手,所以如果不是应该的话,请告诉我。
我有一个带有ParentViewModel的ParentView。 ParentView拥有两个视图SubViewA和SubViewB,它们都有自己的ViewModel。这是我的ParentView.xaml:
<local:ViewBase.DataContext>
<local:ParentViewModel x:Name="Model" />
</local:ViewBase.DataContext>
<Grid>
<local:SubViewA Visibility="{Binding ElementName=Model, Path=SubViewAVisibility}" />
<local:SubViewB Visibility="{Binding ElementName=Model, Path=SubViewBVisibility}" />
</Grid>
我想做什么:SubViewModelB有一个绑定到SubViewB的属性。我想在ParentViewModel中发生某个事件时更改该属性。我想这应该通过将SubViewModelB中的属性绑定到ParentViewModel中的属性来完成,但我不确定如何?我在ParentView.xaml中尝试了类似下面的内容:
<local:SubViewB Visibility="{Binding ElementName=Model, Path=SubViewBVisibility}" SomeProperty="{Binding ElementName=Model, Path=WhatIWantThePropertyToBe}" />
但那让我无处可去。 那么我该如何解决这个问题呢?我知道我可以通过MVVM轻量级工具包中的消息传递来实现它,但这似乎与我想要做的事情不相称。有什么建议吗?
由于
答案 0 :(得分:3)
这对EventAggregator模式来说是一个很好的解决方案。有一些很棒的实现,例如由Microsoft Prism或TinyMessenger提供的(非常轻量级)
作为一个代码示例,你会做这样的事情(使用Prism,未经测试的代码)
public class ParentViewModel
{
private IEventAggregator eventAggregator;
public ParentViewModel(IEventAggregator eventAggregator)
{
this.eventAggregator = eventAggregator;
}
public void PublishSomeEvent()
{
// When a condition occurs, publish an event any subscribers
// that may be listening
this.eventAggregator.GetEvent<SomeEvent>()
.Publish(new SomeEvent("Hello World!")));
}
}
public class SubViewModel
{
private IEventAggregator eventAggregator;
public SubViewModel(IEventAggregator eventAggregator)
{
eventAggregator.GetEvent<SomeEvent>.SomeEvent(OnSomeEventOccurred);
}
public void OnSomeEventOccurred(SomeEvent arg)
{
// This method called when ParentViewModel publishes the event
Console.WriteLine(arg.OptionalMessage);
}
}
您需要单独声明该事件。例如,我使用这个
public SomeEvent : CompositePresentationEvent<SomeEvent>
{
public SomeEvent(string optionalMessage)
{
this.optionalMessage = optionalMessage;
}
public string OptionalMessage { get { return optionalMessage; } }
}
答案 1 :(得分:1)
您的SubViewModel
权利中会有ParentViewModel
的实例吗?如果您这样做,则可以在ParentViewModel
中捕获事件并手动更改SubViewModel
的特定属性值。
我不确定这是否是完美的方式,但这应该做的工作。
另一种方法是直接使用ParentViewModel
中的属性绑定SubView的属性尝试这样的事情
Binding="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type Window}}, Path=DataContext.ParentViewModelProperty}"