使用 MVVM 模式从具有单独视图模型的子 WPF window 获取值

Getting a value from a child WPF window that has a seperate viewmodel using the MVVM pattern

我在我的第一个 MVVM WPF 应用程序上取得了相当大的进步,我现在遇到的问题是我有一个 Window 有一个视图模型。
这个 window 有一个按钮可以打开另一个 window 有另一个视图模型。 假设第一个 window.
上有一个文本框,一旦打开第二个,用户将 select 一个值并单击保存,这个 window 将关闭并更新第一个 window 及其值。
推送保存时,我在调用 SaveMethod 的 childwindows Viewmodel 上有一个 ICommand。我将 selected 值存储在子 windows 视图模型的 属性 中。

但是如何更新 Main Windows这个值的文本框?我想我在主 windows 视图模型上绑定了一个 属性,但不确定如何继续。

请指教,如果需要,我可以提供代码示例,但我想我可能已经解释得足够好了,
哦,感谢 Whosebug 的每个人对我的问题的帮助,我学到了很多东西.

在父视图模型中,您需要引用子视图模型。当子 window 关闭时,您需要获取第二个视图模型的 属性 的值并将其设置为第一个父视图模型的适当 属性。

使用 MVVM Light 框架非常简单。出于演示的目的,我将使用字符串作为您传递的值,但是很容易为您需要传递的任何内容构造不同的消息类型。

在第一个 Window 的 ViewModel 的构造函数中注册接收 NotificationMessages。 NotificationMessages 用于发送字符串消息:

public MyFirstViewModel()
{
    Messenger.Default.Register<NotificationMessage>(this, NotificationMessageReceived);
}

在第二个 Window 的 ViewModel 的 SaveMethod 中,您发送一条消息,其中包含您要传递的值。我使用 MyStringValue 作为 属性 的名称,它存储用户在第二个 Window:

中选择的值
private void SaveMethod()
{
    MessengerInstance.Send(new NotificationMessage(MyStringValue));
}

当第一个 Window 的 ViewModel 收到该消息时,将调用 NoitificationMessageReceived 方法。我打算将该值放入第一个名为 MySavedValue:

的 ViewModel 的字符串 属性 中
private void NotificationMessageReceived(NotificationMessage msg)
{
    MySavedValue = msg.Notification;
}

在第一个 Window 的视图中,您有一个文本框,其文本 属性 绑定到 MySavedValue。每当更新 MySavedValue 时都会更新。

一种可能的(也是简单的)解决方案是为两者保留一个 ViewModel windows

<Grid>
    <StackPanel>
        <TextBox Text="{Binding TheText}" />
        <Button Command="{Binding ShowOptionsCommand}" Content="..."/>
    </StackPanel>
    <Popup IsOpen="{Binding IsShowingOptions}">
        <StackPanel>
            <ListBox ItemsSource="{Binding Options}" 
                    SelectedItem="{Binding SelectedOption,Mode=TwoWay}"/>
            <Button Command="{Binding SaveOption}">Save</Button>
        </StackPanel>
    </Popup>
</Grid>

//ShowOptionsCommand handler
void ShowOptions() 
{
    IsShowingOptions = true;
}
//SaveOptionCommand handler
void SaveOption() 
{
    TheText = SelectedOption;
    IsShowingOptions = false;
}

我正在使用 Popup 来简化示例。

我个人会选择已经提到的 mvvm light 框架,但另一种选择是利用 IOC,它也包含在上述框架中。

使用此模式,视图模型具有接口并绑定为来自视图模型定位器数据源的属性。其中,子视图模型可以注入父视图模型。因为 IOC 可以创建对象的单例实例,所以将相同的实例提供给父实例,就像绑定到子实例一样 window。这样你就可以通过一个接口获得对视图模型的引用,从而保持分离。

只是将此作为现有技术解决方案之外的替代技术解决方案提供。