了解WPF - 在模型或ViewModel中存储数据

时间:2015-10-22 14:58:10

标签: c# wpf mvvm

我不确定将数据存储在WPF应用程序中的何处。有两个原则可能会发生冲突。有人可以解决这个问题吗?

原则1:数据应存储在模型中 接下来,例如,ObservableCollection<string> Articles应存储在模型中。 ViewModel中的Property可以使其可用于View。

原则2:依赖于View的状态应存储在ViewModel中 这意味着具有相应属性string _SelectedArticle的{​​{1}}变量应存储在ViewModel中。

到目前为止,我只将不影响View的方法或值放入模型中,因为我(也许)强烈遵循原则2.但我不确定这是否是正确的方法。< / p>

我是否应该在模型中保留一些数据,在ViewModel中保存一些数据,还是存放所有数据?

3 个答案:

答案 0 :(得分:4)

简单的答案是:数据应该存储在它所属的位置。

  • 模型应仅包含数据本身 - 它可能包含您从外部服务,用户输入,数据访问层和其他数据获得的数据。
  • ViewModel应将部分数据(将向用户呈现)包装到适当的包装中,以提供查看和更改数据的能力 - 公共属性,ObservableCollections等。如果有相同数据的许多可视化表示您的应用,然后您必须为每个表示(视图)构建适当的ViewModel。
  • View使用ViewModel,但还可以在其中包含一些验证(非验证)逻辑和相关参数。

在您的情况下,模型应该有:app:mergeDebugResources FAILED FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':app:mergeDebugResources'. > Error: com.google.common.util.concurrent.UncheckedExecutionException: java.lang.RuntimeException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 1 * Try: Run with --info or --debug option to get more log output. * Exception is: org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':app:mergeDebugResources'. at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:69) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:46) at org.gradle.api.internal.tasks.execution.PostExecutionAnalysisTaskExecuter.execute(PostExecutionAnalysisTaskExecuter.java:35) at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:64) at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58) at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:42) at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52) at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:53) at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43) at org.gradle.api.internal.AbstractTask.executeWithoutThrowingTaskFailure(AbstractTask.java:310) at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.executeTask(AbstractTaskPlanExecutor.java:79) at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:63) at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:51) at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54) at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40) Caused by: com.android.build.gradle.tasks.ResourceException: Error: com.google.common.util.concurrent.UncheckedExecutionException: java.lang.RuntimeException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 1 at com.android.build.gradle.tasks.MergeResources.doFullTaskAction(MergeResources.java:164) at com.android.build.gradle.internal.tasks.IncrementalTask.taskAction(IncrementalTask.java:104) at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:75) at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$IncrementalTaskAction.doExecute(AnnotationProcessingTaskFactory.java:243) at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:219) at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$IncrementalTaskAction.execute(AnnotationProcessingTaskFactory.java:230) at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:208) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:80) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:61) ... 14 more Caused by: Error: com.google.common.util.concurrent.UncheckedExecutionException: java.lang.RuntimeException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 1 at com.android.ide.common.res2.MergeWriter.end(MergeWriter.java:54) at com.android.ide.common.res2.MergedResourceWriter.end(MergedResourceWriter.java:129) at com.android.ide.common.res2.DataMerger.mergeData(DataMerger.java:291) at com.android.ide.common.res2.ResourceMerger.mergeData(ResourceMerger.java:48) at com.android.build.gradle.tasks.MergeResources.doFullTaskAction(MergeResources.java:157) ... 22 more Caused by: java.lang.RuntimeException: com.google.common.util.concurrent.UncheckedExecutionException: java.lang.RuntimeException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 1 at com.android.ide.common.internal.WaitableExecutor.waitForTasksWithQuickFail(WaitableExecutor.java:117) at com.android.ide.common.res2.MergeWriter.end(MergeWriter.java:50) ... 26 more Caused by: com.google.common.util.concurrent.UncheckedExecutionException: java.lang.RuntimeException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 1 at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2201) at com.google.common.cache.LocalCache.get(LocalCache.java:3934) at com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:3938) at com.google.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:4821) at com.android.ide.common.blame.MergingLog.getWholeFileMap(MergingLog.java:128) at com.android.ide.common.blame.MergingLog.logCopy(MergingLog.java:88) at com.android.ide.common.blame.MergingLog.logCopy(MergingLog.java:98) at com.android.ide.common.res2.MergedResourceWriter$1.call(MergedResourceWriter.java:215) at com.android.ide.common.res2.MergedResourceWriter$1.call(MergedResourceWriter.java:171) Caused by: java.lang.RuntimeException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 1 at com.android.ide.common.blame.MergingLogPersistUtil.loadFromSingleFile(MergingLogPersistUtil.java:293) at com.android.ide.common.blame.MergingLog$1.load(MergingLog.java:55) at com.android.ide.common.blame.MergingLog$1.load(MergingLog.java:52) at com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3524) at com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2317) at com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2280) at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2195) ... 8 more Caused by: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 1 at com.google.gson.stream.JsonReader.syntaxError(JsonReader.java:1505) at com.google.gson.stream.JsonReader.checkLenient(JsonReader.java:1386) at com.google.gson.stream.JsonReader.doPeek(JsonReader.java:572) at com.google.gson.stream.JsonReader.beginArray(JsonReader.java:332) at com.android.ide.common.blame.MergingLogPersistUtil.loadFromSingleFile(MergingLogPersistUtil.java:266) ... 14 more BUILD FAILED 。 ViewModel将使用此列表并在构造函数中构建List<string> ArticlesObservableCollection<string> Articles也应存储在ViewModel中,如果其值仅用于在View中导航,并且永远不会在模型中使用或保存到数据访问层中的某个位置。

答案 1 :(得分:1)

模型应该包含需要保存的所有数据,例如,模型包含名字,姓氏,出生日期等的人物对象。

viewmodel然后包装此模型并应用在View和模型之间传递数据所需的任何逻辑,因此如果您想要Age字段,那么您不会在模型中保存年龄,而是指示视图模型计算它从DOB传递到视图,同样的业务规则,如输入验证发生在View模型级别,所以如果你的人必须超过18岁,你需要检查出生日期,然后再将其传递给模型进行保存,您还可以使用视图模型进行更改跟踪,因此如果您更改名字,则视图模型会引发属性更改事件而不是模型

然后视图控制如何显示数据,因此指示哪些控件链接到ViewModel中的哪些属性

大多数可选择的控件将其选定值定义为功能的一部分,因此如果您希望控件A显示在控件B中选择的内容,则将控件A绑定到控件B的所选项属性

在您的情况下,我希望看到一个控制数据库访问或Web服务等的文章模型

显示文章文本的ArticlesEditor ViewModel允许使用Save和cancel方法更改它,该方法可以从模型重新加载原始文本或将更改的文本复制到模型

然后是一个ArticlesList视图模型,其中包含一个可观察的ArticlesEditor集合,并包含创建和删除文章的方法

然后在你的视图中你将有一个listview绑定到ArticlesList.Articles属性,你的编辑器控件绑定了ListViews.SelectedItem属性,然后编辑器控件的控件将被绑定到ArticlesEditor对象的属性

答案 2 :(得分:0)

View 可见的所有数据都应存储在 ViewModel 中。 只需使用调用业务逻辑的viewmodel。 如果您的实体未映射到视图(如果您显示某些内容),则应使用模型,而不是其视图模型。