c# - 如何在 ViewModel 之间访问数据?

标签 c# wpf mvvm viewmodel

我目前正在做一个项目,为了简化解释,假设在一个 TabControl 中有两个选项卡...

在一个选项卡中,您可以将文件夹添加到列表框。

在另一个选项卡中,有一个列表框显示您添加的所有文件夹中的所有项目。

每个选项卡都是一个 ViewModel(这是为了简化代码,因为将所有代码转储到一个 ViewModel 中会使其难以阅读和理解)。

为了让这个程序工作,两个 ViewModel 都需要访问项目列表:一个因为它必须显示它们,另一个因为它必须添加到它们。

我不知道该怎么做。我最初认为共享数据不好,一开始就不应该发生这种情况,但后来我意识到我想不出任何其他方法来做到这一点。

我是 MVVM 的新手(这是我使用 MVVM 的第一个真正的应用程序)并且最初开始使用它,因为我无法在类之间访问数据,并且认为 MVVM 会以某种方式解决这个问题,但我又来了。

如果有人能告诉我如何做到这一点,并可能用示例代码进行解释,我将不胜感激。我也乐于接受对我的方法的建议和建设性批评。

最佳答案

首先,您应该了解 MVVM 中的View 是什么。把它看成一个面板。可以嵌入 Window、TabControl 甚至 ListBox 项中的面板。还可以包含子面板的面板。基本上,如果您的应用程序不仅仅是一个简单的输入表单,那么它很可能会有多个View。不要试图将所有内容都放在一个 View/ViewModel 中,因为这会使以后的事情变得非常复杂。您希望拥有所谓的 View 层次结构 及其相应的ViewModels。会有很多 Views/ViewModels 但它们相对简单且易于维护(这里是使用 PRISM 在 View 之间切换的小示例,但您可以获得主要的想法 https://youtu.be/ZfBy2nfykqY?t=45m34s )。

Each tab is a ViewModel (this is to simplify code, as dumping all the code in one ViewModel makes it hard to read and understand).

这是正确的做法。下面是一些伪代码,描述了您的示例应用程序方案应该是什么样子:

// MODEL:

public class Model
{
    ObservableCollection<Item> ListOfItems;
}

public class Item
{
}

// VIEWMODELS:

public class MainWindowViewModel
{
    Model Model { get; set; }

    Tab1ViewModel Tab1ViewModel { get; set; }
    Tab2ViewModel Tab2ViewModel { get; set; }

    public MainWindowViewModel()
    {
        Model = new Model();
        Tab1ViewModel = new Tab1ViewModel(Model);
        Tab2ViewModel = new Tab2ViewModel(Model);
    }
}

public class Tab1ViewModel
{
    ObservableCollection<ItemViewModel> ItemViewModels { get; set; } // Bind it to ListBox's ItemsSource

    public Tab1ViewModel(Model m)
    {
        ItemViewModels = new ObservableCollection<ItemViewModel>();
        // Populate ItemViewModels and keep it in sync with ListOfItems model by subscribing to its CollectionChanged event.
    }
}

public class Tab2ViewModel
{
    ObservableCollection<ItemViewModel> ItemViewModels { get; set; } // Bind it to ListBox's ItemsSource

    public Tab2ViewModel(Model m)
    {
        ItemViewModels = new ObservableCollection<ItemViewModel>();
        // Populate ItemViewModels and keep it in sync with ListOfItems model by subscribing to its CollectionChanged event.
    }

}

public class ItemViewModel
{
    Item Item { get; set; } // Model

    public ItemViewModel(Item item)
    {
        Item = item;
    }
}

现在您可以在不同的 View 中显示相同的数据并对其执行不同的操作。每个 View 都会自动更新,因为它引用相同的模型

您还可以使用 EventAggregator 或类似的东西在 ViewModels 之间进行通信。

尽量避免使用可以从应用程序中的任何位置访问的数据的静态类/单例,因为这违反了封装原则。

关于c# - 如何在 ViewModel 之间访问数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43021314/

相关文章:

c# - Starfield 屏保方程式

javascript - Dynamics CRM - 从自定义设置页面添加/删除事件

c# - 匿名结构声明

wpf - 属性更改后列表框不刷新

c# - 窗口内弹出窗口 : How to block UI thread?

c# - 如何将按钮添加到 HeroCard 并在单击时选择值

WPF 应用程序和操作系统

c# - 如何在绑定(bind)失败时避免设置本地值(因此继承的值将传播)

c# - 从另一个 UserControl 在 MainWindow 中添加 UserControl

c# - 如何使用 ViewModel-First 方法从 ViewModel 调用 View 方法