【问题标题】:how to avoid multiple views reciving data from same viewmodel如何避免多个视图从同一个视图模型接收数据
【发布时间】:2013-07-08 12:44:21
【问题描述】:

我对我的代码的行为有点困惑。我还是 MVVM 领域的新手。

我有命令显示的 NewMessageWindow

    private ICommand newMessageCommand;
    public ICommand NewMessageCommand
    {
        get
        {
            if (newMessageCommand == null)
                newMessageCommand = new RelayCommand(() =>
                {
                    new NewMessageWindow().Show();
                });
            return newMessageCommand;
        }
    }

可以有多个 NewMessageWindows,每个都应该有单独的 ViewModel。但是我注意到当我打开多个窗口时,如果我在其中更改某些内容,它会影响所有窗口。例如,当我更改组合框时,所有窗口中的组合框值都会发生变化。

如何避免?如何使用不会相互影响的单独视图模型打开多个窗口?

正在改变的对象是绑定到视图的ObservableCollections

编辑:

这就是 ViewLocator 的样子

    public NewMessageWindowModel NewMessage
    {
        get
        {
            return ServiceLocator.Current.GetInstance<NewMessageWindowModel>();
        }
    }

在构造函数中

    SimpleIoc.Default.Register<NewMessageWindowModel>();

这是绑定的样子:

 DataContext="{Binding NewMessage,
                          Source={StaticResource Locator}}"

我已经解决了问题

 ServiceLocator.Current.GetInstance<NewMessageWindowModel(System.Guid.NewGuid().ToString());

但我读过旧实例已被缓存。如何摆脱它们?

【问题讨论】:

  • 每个视图都有自己的视图模型吗?如果视图都具有相同的视图模型,那么您的 INofifyPropertyChanged(或类似的 MVVM 实现)将通知所有窗口并进行相应更改。
  • 如何查看?他们都在扩展ViewModelBase
  • 没有看到更多代码很难说;我假设您的视图是 XAML 窗口,您是否将每个数据上下文设置为不同视图模型的数据上下文?
  • 那么您在哪里为NewMessageWindow 创建虚拟机?您可以在此处检查它是否确实为每个 View 实例创建了新的虚拟机
  • 它们是 xaml 窗口这是我设置 dataContext DataContext="{Binding NewMessage, Source={StaticResource Locator}}"

标签: c# .net wpf mvvm mvvm-light


【解决方案1】:

来自 MVVM Light 的SimpleIoC 不会在每次调用 ServiceLocator.Current.GetInstance&lt;...&gt;(); 时创建一个新 VM

你可以从库的作者那里找到解释,每次都得到一个新的虚拟机Here

对于你的情况,

我可能只是在 NewMessageWindow 的代码隐藏构造函数中设置 DataContext,而不是直接在 xaml 中使用类似的东西:

public NewMessageWindow() {
  InitializeComponent();
  var uniqueKey = System.Guid.NewGuid().ToString();
  DataContext = SimpleIoc.Default.GetInstance<NewMessageWindowModel>(uniqueKey);
  Closed += (sender, args) => SimpleIoc.Default.Unregister(uniqueKey);
}

这样当Window关闭时,虚拟机将从缓存中移除。

请注意,这不是唯一的方法,您还有很多其他选择,

  • 您可以将DataContext 的绑定保留在xaml 中,当Window 关闭时,使用MVVM Light 中的Messenger 类向ViewModelLocator 发送消息以删除缓存。
  • 您可以在ViewModelLocator 中实现Cleanup() 函数,以在出现键时删除缓存。

选择一个您喜欢的实现并使用它,或者使用类似Unity 或其他 DI 容器帮助器来获得对 VM 对象生命周期的更多控制。

【讨论】:

  • 我已将代码放在视图中,但它不起作用,唯一有效的解决方案是使用 return ServiceLocator.Current.GetInstance&lt;NewMessageWindowModel&gt;(System.Guid.NewGuid().ToString()); 但这样我不知道如何摆脱缓存的窗口.
  • @Robert 我在代码粘贴中做了一些编辑,你确定你复制的是最新的吗?还要确保从NewMessageWindow.xaml 中删除DataContext 的xaml 绑定
  • 在您编辑代码后,它就可以工作了。我会接受答案。感谢您的宝贵时间。
【解决方案2】:

这种行为是因为 Servicelocator。它返回对象的相同实例。您可以在其中获得所有共享实例的更改。如果您想拥有 ViewModel 的单独副本。您可以将 GetNewInstance 实现到服务定位器中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-09
    • 1970-01-01
    相关资源
    最近更新 更多