在视图模型之间共享数据 | 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")。
你好堆栈的好人溢出。
编辑:源代码可用于: 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")。