【问题标题】:Save and Load data "the MVVM" way?以“MVVM”方式保存和加载数据?
【发布时间】:2014-09-24 20:08:45
【问题描述】:

我目前正在使用 Telerik 提供的一些控件进行 C# WPF 项目,我尊重 MVVM 模式:

  • 包含数据的模型

  • 将数据呈现给视图的 ViewModel

  • 显示数据的视图

当然,某些模型可以重复使用并显示在多个视图中(在我的情况下,数据可以是显示在不同图表上的形状的内容)。

现在我开始设计如何保存数据。我的目标很简单:当用户离开应用程序并返回时,所有视图在内容、颜色、字体、大小、空间位置等方面都必须相同......

保存模型仅涵盖内容部分。您将如何保存显示属性,如颜色、字体、空间位置,尤其是当多个 View 依赖于同一个 Model 时?我应该使用 Bindings 并将所有属性从 View 移动到 Model 吗?有模型复杂度会大大增加的风险吗?

您有什么解决方案可以将 UI 属性与模型分开吗?

还有关于如何“以 MVVM 方式”保存和加载数据的最佳实践吗?

提前致谢。

【问题讨论】:

  • 是的,你是对的,你应该将所有这些属性移动到你的模型中。
  • 视图相关的东西就是视图相关的东西。您可以创建一些服务接口或方法,它们与您的模型在相同或不同的持久层上工作,并在与视图相关的代码隐藏中使用此服务(或方法)来保存/加载 UI 状态。但是我不会将模型和视图模型与完全纯粹与视图相关的东西混合在一起。 (我说的是虚拟机不应该关心的东西,例如文本是否是黑底白字而不是白底黑字,或者用户是否使可调整大小的面板比另一个大一点。 ..)
  • @elgonzo :我比我更喜欢您的解决方案,因为您将“业务”属性和“显示”属性分开。但是当我如此努力地将其保持在最低限度(如 DataContext)时,添加代码隐藏让我感到难过。您是否阅读过任何描述您的服务接口或方法的文章或博客文章?
  • 对于服务/方法,我只是指一些工具来加载/保存您的设置(就像您有类似数据服务的东西来加载/保存/持久化您的模型)。我通常做的是让一个类型具有一个(单例)实例,可通过UISettings.Instance 之类的静态属性访问。此实例可能具有带有 UI 设置的属性或特定于某些窗口/UI 元素的进一步“配置容器”。然后,在 XAML 中,您可以访问类似 "{Binding SomeProperty, Source={x:Static local:UISettings.Instance}}" 的 UI 设置(也许您还需要声明 TwoWay 模式)
  • 另一方面,您可以直接使用设置工具,而不是旋转您自己的 UISettings 类(就像我一样,但话又说回来,我们的应用程序有点大,并且有一些阴暗的历史......)在您的 C# 项目中默认提供(请参阅 Sheridan 的回答)。绑定到 Settings 对象将类似于我之前所说的:"{Binding SomeProperty, Source={x:Static YourNamespace:Settings.Default}}"YourNamespace 将是类似于 YourProject.Properties 命名空间的命名空间)

标签: c# wpf mvvm save persistence


【解决方案1】:

我将类似的用户选项保存在应用程序设置中。如果您不熟悉它们,可以在 MSDN 上的 Using Settings in C# 页面上找到完整的故事。简而言之,您可以拥有应用程序和用户设置,听起来您希望每个用户保存用户设置。 UI 属性在任何模型中都没有位置,因为将此类信息与模型数据一起存储没有任何好处。你可以对他们做这样的事情:

private void LoadSettings(MainWindow window)
{
    Settings.Default.Reload();
    window.WindowStartupLocation = WindowStartupLocation.Manual;
    window.Left = Settings.Default.ApplicationLocation.X;
    window.Top = Settings.Default.ApplicationLocation.Y;
    window.Width = Settings.Default.ApplicationSize.Width;
    window.Height = Settings.Default.ApplicationSize.Height;
    window.WindowState = Settings.Default.IsApplicationMaximised ? WindowState.Maximized : WindowState.Normal;
}

private void SaveSettings(MainWindow window)
{
    Settings.Default.ApplicationLocation = new Point(window.Left, window.Top);
    Settings.Default.ApplicationSize = new Size(window.Width, window.Height);
    Settings.Default.IsApplicationMaximised = window.WindowState == WindowState.Maximized;
    Settings.Default.Save();
}

将一些属性添加到基本或主视图模型可能更容易,以便您可以将数据绑定到它们:

public void SaveSettings(string tabName)
{
    Settings.Default.ReleaseTrackSideFormat = StateManager.ReleaseTrackSideFormat;
    Settings.Default.ReleaseLabelCopyFormat = StateManager.ReleaseLabelCopyFormat;
    Settings.Default.ReleaseExportDestination = StateManager.ReleaseExportDestination;
    Settings.Default.ReleaseSearchOptions = new SerializableReleaseSearchOptions(ReleaseSearchOptions);
    ...
    Settings.Default.Save();
}

public void LoadSettings()
{
    Settings.Default.Reload();
    StateManager.ReleaseTrackSideFormat = Settings.Default.ReleaseTrackSideFormat;
    StateManager.ReleaseLabelCopyFormat = Settings.Default.ReleaseLabelCopyFormat;
    StateManager.ReleaseExportDestination = Settings.Default.ReleaseExportDestination;
    ReleaseSearchOptions = new ReleaseSearchOptions(Settings.Default.ReleaseSearchOptions);
    ReleaseExportSearchOptions = new ReleaseExportSearchOptions(Settings.Default.ReleaseExportSearchOptions);
    ...
}

更新>>>

您说的很对……您不希望以这种方式存储模型数据。这是针对与 UI 相关的用户首选项。如果您还询问如何保存模型数据,那么快速回答是我会将我的数据存储在数据库中,但这取决于您。您可以轻松地将其存储在计算机上的文件中。这一切都取决于规模、便利性、速度、资源访问等,所以这不是一个真正适合本网站范围的问题。

但是,网上有很多教程逐步展示了保存数据的不同方法。要回答 那个 问题,我建议您关注其中的一些问题。

我可以告诉您的是,习惯上将您的数据访问代码放入单独项目(或小项目的文件夹)中的类中。此类通常仅在父视图模型属性或基础视图模型属性中引用,并且所有子视图模型都将通过此访问它们的数据......也许是这样的:

protected IModel Model
{
    get { return model; }
}

然后子视图模型会像这样使用它:

SomeCollectionProperty = Model.GetSomeData();

或者:

Model.SaveSomeData(SomeCollectionProperty);

为了进一步澄清,在这个阶段你对这个Model 类有什么实现没有区别。只要实现GetSomeDataSaveSomeData 方法,视图模型不关心它是使用数据库还是普通的旧文本文件。因此,在这里使用接口是很好的,尤其是当您想要对视图模型进行任何测试时。

最后,您可能想看看我对Project structure for MVVM in WPF 问题的回答,以更好地了解这一点。

【讨论】:

  • 我不确定我们是否可以认为我的项目的“显示”属性是用户设置。想象一下,应用程序将显示一个包含 20 个形状的图表。每个形状都绑定到模型中保存的内容。并且您想保存每个形状在空间中的位置。你会用用户设置来做吗?
猜你喜欢
  • 1970-01-01
  • 2013-06-23
  • 1970-01-01
  • 1970-01-01
  • 2011-05-09
  • 1970-01-01
  • 1970-01-01
  • 2021-10-19
  • 2020-01-22
相关资源
最近更新 更多