【问题标题】:MVVMLight multiple instancekeyed-ViewModels with corresponding ViewsMVVMLight 具有对应视图的多个实例键控视图模型
【发布时间】:2018-04-13 18:56:15
【问题描述】:

它可能是一个转储主题标题,但我不知道如何总结这个问题。

首先,我是 MVVM 和 MVVMLight 的新手。

我正在尝试创建特定视图模型(例如 GalleryViewModel)的多个实例,并在绑定到 GalleryViewModel 特定实例的相应视图中显示相应数据。因此,用户打开了(例如)五个 GalleryView,而在后台,每个 GalleryView 都必须绑定到相应的 GalleryViewModel。

因此,我使用 GUID 作为 InstanceKey 调用 SimpleIoC 的“GetInstance”。

问题是,这样,当视图模型中的数据发生变化时,视图不会更新。我发现,只有当我使用实例键实例化视图模型时,才会出现这种情况。

所以我认为,我必须使用 instancekey XY 将当前视图链接/绑定到该视图模型。但我不知道该怎么做。

我的“架构”是这样的:MainViewModel 调用 GetInstance(GUID) 方法。在 MainView 中,使用 GalleryView 显示/创建一个新的 UserControl。它的数据上下文通过 XAML 绑定到 GalleryViewModel(但这可能是问题所在,因为此绑定不知道 GUID,因此它可能会绑定到错误的实例 (?) 并且 DataBindings 不会得到更新。

这是一些代码:

ViewModelLocator 只返回一个实例(也许这就是问题所在)

public GalleryMainViewModel Gallery
{
    get { return ServiceLocator.Current.GetInstance<GalleryMainViewModel>(); }
}

从 MainViewModel 中调用“导航”(尽管我的应用程序缺少 NavigationInterface(现在)。

private void DoOpenTab(string windowname, string payload = null)
        {
            DockWindowViewModel window;
            string guid;            
            switch(windowname)
            {                    
                case "Gallery":
                    guid = Guid.NewGuid().ToString();
                    window = ServiceLocator.Current.GetInstance<GalleryMainViewModel>(guid);
                    window.ViewModelInstanceKey = guid; 
                    Messenger.Default.Send(
                        new NotificationMessage(payload), 
                        (window as GalleryMainViewModel).MessageToken);
                    DockManagerViewModel.AddDocument(window);
                    break;
            }
        }

GalleryView(这是一个放置在 Avalon DockManager-Tab 中的 UserControl)看起来像这样

<src:PluginView
    DataContext="{Binding Gallery, Source={StaticResource Locator}}"
    <!-- just normal bindings. -->
</src:PluginView>

希望有人能帮帮我。我感觉非常接近解决方案,但我真的不知道如何完全解决它。

提前致谢!

【问题讨论】:

    标签: c# wpf xaml mvvm mvvm-light


    【解决方案1】:

    如果它在您的定位器中

       public GalleryMainViewModel Gallery
        {
            get { return ServiceLocator.Current.GetInstance<GalleryMainViewModel>(); }
        }
    

    这在你的视野中

    <src:PluginView
        DataContext="{Binding Gallery, Source={StaticResource Locator}}"
        <!-- just normal bindings. -->
    </src:PluginView>
    

    那么使用 guid 创建的虚拟机可能永远不会绑定到视图。这取决于视图接收到通知消息时会发生什么。

    上面的代码告诉视图通过 Gallery 属性直接从定位器获取它的 DataContext。正如您所说,对于此视图的所有实例,这将是相同的实例。

    【讨论】:

    • 谢谢,我就是这么想的。我怎样才能改变这种行为?这对我来说是新的。我想我理论上知道该怎么做,但我不知道如何在代码中做到这一点。简而言之:如何将视图绑定到特定的 VM 实例?我是否必须在代码隐藏中执行此操作,还是应该通过通知消息(从 VM 到 V 或从 V 到 VM)来完成?你会怎么做?
    • 有多种方法取决于 UserControl 和 VM 在内部执行的操作以及您想要达到的解耦级别。如果 VM 是自包含的,并且在 UserControl 关闭后您不需要它,最简单的方法是让定位器每次返回一个唯一实例,方法是将 Guid.NewGuid().ToString() 放在 Gallery 属性中定位器。
    • 当用户关闭视图时,视图模型也可以被销毁。在那种特殊情况下,用户“声明”不再使用这个 vm-v-combination。如果是这样,他可以重新打开那个画廊(什么会创建一个新的 vm-v-guid-pair。对吗?当用户想要再次重用/重新打开同一对时可能是什么?如何跟踪 vm-v -pairs?这对我来说是新的。到目前为止,谢谢。那天晚些时候我会试试你的解决方案。
    • 我可能会为此考虑一个服务类,我要么提供 guid,它负责查看哪个视图与哪个视图模型一起使用,要么给它 VM 并要求它绑定到看法。这篇文章展示了我试图描述的那种策略的一个简单例子。 DialogService Example
    • 不幸的是,我不熟悉 AvalonDock,所以我不熟悉它如何与 DataContext 的设置交互。可能通过将 VM 添加到 DockManagerViewModel 文档集合中,因为它知道将它与哪个视图关联并绑定它?
    猜你喜欢
    • 2014-08-15
    • 1970-01-01
    • 1970-01-01
    • 2011-08-24
    • 1970-01-01
    • 2014-12-06
    • 2014-01-21
    • 2011-01-01
    • 1970-01-01
    相关资源
    最近更新 更多