在视图模型之间共享数据 | MVVM

Share data between viewmodels | MVVM

你好堆栈的好人溢出

编辑:源代码可用于: https://www.dropbox.com/sh/yq4qbznl4b6gm4h/AADdjd_hb-OQXV5KL8OU5cbqa?dl=0 更具体的 I4PRJ4 --> 后端 --> Backend.sln.

我目前正在制作一个具有 GUI 的产品管理系统。我们决定使用 MVVM,并且我们仍在学习它。 虽然我有问题。在主屏幕上,显示了一个类别列表,并且还显示了所选类别中的产品。

至于现在,我们已经将数据绑定到一个可观察的集合。但是当我们需要使用不同的视图和视图模型添加另一个产品时,问题就出现了。在那种情况下,我们需要有带数据的类别。我们通过主窗口中的命令打开添加产品视图,因此要将数据获取到视图模型,我们必须将对象从 MainWindowViewModel 传递到 AddProductView,然后传递到 AddProductViewModel——这不是我想要的耦合。

所以我尝试使用单例模式,并将可观察集合绑定为:

xmlns:models="clr-namespace:Backend.Models"
..
..
<ListBox Margin="0, 30, 0, 0" ItemsSource="{Binding Source={x:Static models:GlobalCategories.CategoryList}, Path=Name}" DisplayMemberPath="Name"/>

其中GlobalCategories如下:

[模型:GlobalCategories]

public class GlobalCategories
{
    private static BackendProductCategoryList _list;

    public static BackendProductCategoryList CategoryList
    {
        get
        {
            if (_list == null)
            {
                MessageBox.Show("Made new list");
                return new BackendProductCategoryList();
            }
            MessageBox.Show("Returned old list");
            return _list;
        }
        set { _list = value; }
    }
}

正如您在代码中看到的那样,出现了一个消息框,告诉我返回了什么。但是使用上面的 XAML 代码,它实际上创建了那个对象,据我所知,它不会那样做,因此你必须自己初始化它。它实际上创建了对象,并且消息框会说已经创建了一个新列表。

虽然如果我然后在 MainWindowViewModel 中执行以下操作

  public class MainWindowViewModel
{
    public MainWindowViewModel()
    {
        MessageBox.Show("" + CategoryList.Count);
    }

然后它会创建另一个列表,但如果我再执行另一个操作,我会收到 "old list" 消息。这是怎么回事 - 为什么会这样? 我究竟做错了什么?哦 - 绑定不起作用,当我这样做时没有显示任何内容。这让我发疯。我有 C 和 C++ 的背景,并且已经使用 c# 和 xaml 几个月了 - 我需要控制。和指针 :-D

我真的希望你们能在这里帮助我,让我了解发生了什么,以及我如何解决它。

甚至更好 - 是否有更好的视图模型之间共享数据的方法?因为老实说,我不是单身人士的忠实拥护者,并且真的很想在视图模型之间共享数据的另一种解决方案。

非常感谢您的帮助!

此致,

本杰明

我认为您可能对 属性 访问器的工作方式有些困惑。 Set 和 get 只允许您声明成员,这些成员看起来像引用它们但用代码实现的所有内容的常规属性。当某些东西需要访问列表时,它会调用您的 getter 并期望该函数 return 一个值(或空值)。您当前的实施是创建一个新列表并 returning 它:

return new BackendProductCategoryList();

但是您没有在 _list 中设置值,所以下次调用 getter 时,_list 的值仍然为空,您再次创建并 return 列表。又一次,等等。您需要做的就是存储它,以便列表只创建一次:

public static BackendProductCategoryList CategoryList
{
    get
    {
        if (_list == null)
        {
            MessageBox.Show("Made new list");
            _list = new BackendProductCategoryList();
        }
        else
            MessageBox.Show("Returned old list");
        return _list;
    }
    set { _list = value; }
}

一个额外的提示:不要在访问器中调用 MessageBox.Show,您应该在访问器中做尽可能少的工作。出于多种原因,像这样使用静力学确实不是一个好主意,但我会把它留给另一个问题(查找 "dependency injection")。