C# 在MVVM中将对象从父视图传递到子视图
我目前正试图进入WPF和MVVM,但最近遇到了一个我不知道如何解决的问题。我是新来的,所以如果有什么不对劲,请告诉我 我有一个ParentView及其ParentViewModel。ParentView包含两个视图SubViewA和SubViewB,它们都有自己的视图模型。这是my ParentView.xaml:C# 在MVVM中将对象从父视图传递到子视图,c#,wpf,windows,mvvm,communication,C#,Wpf,Windows,Mvvm,Communication,我目前正试图进入WPF和MVVM,但最近遇到了一个我不知道如何解决的问题。我是新来的,所以如果有什么不对劲,请告诉我 我有一个ParentView及其ParentViewModel。ParentView包含两个视图SubViewA和SubViewB,它们都有自己的视图模型。这是my ParentView.xaml: <local:ViewBase.DataContext> <local:ParentViewModel x:Name="Model" /> </
<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>
<local:SubViewB Visibility="{Binding ElementName=Model, Path=SubViewBVisibility}" SomeProperty="{Binding ElementName=Model, Path=WhatIWantThePropertyToBe}" />
我想做的是:SubViewModelB有一个绑定到SubViewB的属性。我想在ParentViewModel中发生特定事件时更改该属性。我想这应该通过将SubViewModelB中的属性绑定到ParentViewModel中的属性来实现,但我不确定如何实现?我在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>
<local:SubViewB Visibility="{Binding ElementName=Model, Path=SubViewBVisibility}" SomeProperty="{Binding ElementName=Model, Path=WhatIWantThePropertyToBe}" />
但这对我来说毫无意义。
那么我该如何解决这个问题呢?我知道我可以通过MVVM light toolkit中的消息传递来实现这一点,但这似乎有点不适合我正在尝试做的事情。有什么建议吗
谢谢您的
父视图模型
中会有子视图模型
的实例,对吗?如果这样做,您只需在ParentViewModel
中捕获事件,并手动更改SubViewModel
的特定属性值
我不确定这是不是一个完美的方式,但这应该做的工作
另一种方法是直接将子视图的属性与ParentViewModel中的属性绑定
试试这样的
Binding="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type Window}}, Path=DataContext.ParentViewModelProperty}"
听起来这是一个很好的解决方案。有一些很好的实现,比如or提供的(非常轻量级) 作为一个代码示例,您可以这样做(使用Prism,未经测试的代码)
公共类ParentViewModel
{
私有事件聚合器;
public ParentViewModel(IEventAggregator事件聚合器)
{
this.eventAggregator=eventAggregator;
}
公共无效PublishSomeEvent()
{
//出现条件时,向任何订阅服务器发布事件
//那可能是在听
this.eventAggregator.GetEvent()
.Publish(newsomeevent(“helloworld!”);
}
}
公共类子视图模型
{
私有事件聚合器;
公共子视图模型(IEventAggregator事件聚合器)
{
eventAggregator.GetEvent.SomeEvent(OnSomeEventOccessed);
}
OnSomeEventOccessed(SomeEvent参数)上的公共无效
{
//此方法在ParentViewModel发布事件时调用
控制台写入线(参数可选消息);
}
}
您需要单独声明事件。比如,我用这个
public SomeEvent : CompositePresentationEvent<SomeEvent>
{
public SomeEvent(string optionalMessage)
{
this.optionalMessage = optionalMessage;
}
public string OptionalMessage { get { return optionalMessage; } }
}
publicsomeevent:CompositePresentationEvent
{
公共事件(字符串可选消息)
{
this.optionalMessage=optionalMessage;
}
公共字符串OptionalMessage{get{return OptionalMessage;}}
}
感谢您的回复。很遗憾,没有,我没有直接访问子视图模型的权限。我的视图自己创建模型。我认为这是MVVM中合适的方式,而且它似乎是视图与其viewmodel之间存在明确关系的唯一方式。谢谢。去了信使的方法,但仍然有帮助。谢谢!我想我可以这样做,但这真的是正确的方式吗?对于一个实际耦合的问题,这似乎是一个非常解耦的解决方案。例如,如果我有多个ParentView,每个都有自己的子视图,那么这个解决方案就不起作用了,不是吗?不过,我只有一个ParentView,所以我想这应该没问题:-)谢谢!这就是路。仅仅因为它们是子视图并不意味着它们需要了解它们的父视图。对于多个ParentView,您可以让ParentView向其子视图传递Guid或某种标识符,该子视图也作为激发事件的一部分传递。然后,他们所需要做的就是检查该标识符,看看所触发的事件是否适合他们。结合依赖注入,它真的让生活变得简单。如果你只是想要轻量的,我会和蒂尼辛格一起去。它是一个单一的cs文件,我已经在生产系统中成功地使用了它。如果这是最佳实践,我将使用它:-)已经在应用程序的其他地方使用了MVVM light messenger系统,因此它也很容易实现;-)谢谢你们这么快responses@MarioEmantsal你可以尝试的另一件事是多重绑定,但我不推荐太多的Xaml黑客来让你的应用程序在视觉上工作。最好是在代码中明确,并围绕代码进行一些单元测试。另一种方法是提取一个名为VisibilityManager的类,并将其作为依赖项(通过接口)注入到两个viewmodel中,以根据逻辑/条件处理viewmodel之间的可见性