MVVM和数据模板

本文关键字:数据 MVVM | 更新日期: 2023-09-27 18:01:06

我问了一个关于将多个视图模型映射到单个视图的问题(此处)。我得到了一些很好的答案,但我仍然很难将我在那里学到的东西应用到我的特定案例中。

简单回顾一下:我想创建一个基础ItemViewModelBase类,公开我的视图将绑定到的属性。然后我将创建两个特定的视图模型,PeopleViewModel和CarsViewModel。这两者都继承自ItemViewModelBase并实现了相应的属性。现在,我希望能够创建一个视图,根据它绑定到的视图模型显示适当的信息。由于PeopleViewModel和CarsViewModel都公开了相同的属性,并且我希望这两个视图看起来都一样,所以我只需要一个视图。

在我之前的问题中,有一个答案建议使用DataTemplate:

<DataTemplate DataType="{x:Type ItemViewModelBase}">
   //some user control
</DataTemplate>

我刚开始将DataTemplates与MVVM(以及一般的MVVM)一起使用,所以我有几个问题:

现在ItemViewModelBase是一个抽象类,我定义了相应的属性(ItemName、Items等)

public virtual ObservableCollection<???> Items { get; set; }
  • 我会把什么作为集合类型?从这个基类派生的类将有不同的列表(Person、Car)。基础视图模型是放置属性的正确位置吗?我确实希望所有的派生类都能实现它,所以看起来是这样。而且让Person和Car扩展一些基本对象是没有意义的。

  • 比方说,我不需要对我的观点进行任何定制。在这种情况下,我只需要一个视图。目前还不清楚我会如何设置。我应该为ItemViewModelBase创建一个DataTemplate和一个单独的视图(用户控件)来表示它吗?现在我使用Unity来注册我的视图模型,当创建视图时,视图模型会被注入到视图中。当我尝试创建视图时,如何区分不同的视图模型?

基本上,我不知道在使用DataTemplates时如何显示适当的视图。在我的应用程序中,我现在有一个窗口,其中包含一个定义如下的选项卡控件:

<Grid>
    <TabControl TabStripPlacement="Left" ItemsSource="{Binding TabItems}"/>
</Grid>

TabControl的样式包含以下设置程序:

<Setter Property="Header" Value="{Binding Header}"/>
<Setter Property="Content" Value="{Binding Content}"/>

TabItems的定义如下:

public ObservableCollection<ConfigTabItem> TabItems { get; set; }
TabItems.Add(new ConfigTabItem() { Header = "People", ResolveView = (Func<object>)(() => (PeopleView)Container.Resolve(typeof(PeopleView), "peopleView")) });
TabItems.Add(new ConfigTabItem() { Header = "Cars", ResolveView = (Func<object>)(() => (CarsView)ConfigurationModule.Container.Resolve(typeof(CarsView), "carsView")) });

因此,就目前的情况而言,我有单独的视图模型和People和Cars的视图,每当单击选项卡时,就会解析相应的视图。

我想将此设置更改为使用上面提到的基本视图模型类和带有DataTemplates的单个视图。

任何示例代码/示例都将受到极大的赞赏,显示基本视图模型类、扩展该基本视图模型的一些其他视图模型类,然后能够显示基于视图模型的适当视图(其中只有一个通用视图)。

MVVM和数据模板

IMHO,你在一个问题上问得太多了。试着让你的代码在使用或不使用DataTemplates的情况下工作(如果需要的话,让它变得粗糙),然后专注于你认为需要改进的代码的一个领域,并发布一个关于如何解决特定问题的问题。我开始打一个答案,很快就变得太复杂了,无法表达出整体建议。

我不确定你在关于DataTemplates的另一个问题中是否得到了好的建议。我还非常关心如何设置ConfigTabItem——它似乎是一个使用容器(直接使用容器,这不是一个好的做法)来解析视图的父视图模型,该视图可能也有自己的视图模型。这似乎是不必要的复杂。

无论如何,再次尝试将其提炼为几个重点问题。如果其中任何一个都有帮助,我最初的答案如下(未经编辑):


首先,我不确定我是否理解您在上一个关于DataTemplates的问题中给出的答案。如果您总是绑定到ItemViewModelBase,我不清楚为什么需要指定DataType(甚至DataTemplate)。这并不是说使用DataTemplate是个坏主意,但我不确定在这种情况下是否有必要使用它。

我还想说,我也不确定我是否认为继承的必要性。数据绑定在运行时工作,除了基于VM类型切换DataTemplate(正如我所说,我认为您不需要)之外,视图并不关心它绑定到什么,只要它要查找的属性在运行时找到即可。

因此,一般来说,我将从您的视图模型的一个具体实现开始。让它正确绑定,然后确定可以将它的哪些部分抽象到基类或接口中,如果是您想要采取的方法。这不是必要的,但可能有助于使绑定的要求更容易"强制执行"——例如,使用基类或接口会限制您(或其他人)更改绑定所需的属性的名称。

我会把什么作为收藏品类型派生自的类这个基类将有不同的列表(人员、车辆)。是基础视图为放置所有物我确实想要所有衍生的类来实现它是的。而且拥有人和车扩展了一些基础对象

如果您要为VM使用基类或接口,并且希望集合成为其中的一部分,那么它的类型可以简单地为ObservableCollection<object>。添加到其中的项都需要具有与XAML中引用的属性名称相匹配的属性名称。因此,如果你只想要一个视图,就不能有"PersonName"answers"CarName"属性;您需要使用更通用的东西,如"ItemName"(除非您将DataTemplates与DataTypes一起使用——这是实际有用的地方)。同样,您不需要每个集合项都从基类型继承或实现公共接口,除非(再次)您希望在编译时强制执行。

查看Microsoft App Studio中的通用应用程序体系结构。根据微软应用程序工作室的说法,数据模板应该位于视图目录下的数据模板子目录中。通用应用程序的Windows UI和Windows Phone UI都有此目录,因此它不在共享项目中,因为它们不相同。不要使用Converge PRISM架构。设计完全错误!这并不是在考虑Windows和Windows Phone体系结构的情况下编写的,但就像他们所说的聚合。它应该像在微软应用程序工作室中一样进行彻底的重新设计。不要寻找依赖注入,它不在其中,也不需要。大多数对存根或伪接口使用依赖注入。设计数据的DataContext现在可以很好地处理json数据,以至于依赖注入组件会被过度使用。