我问了一个关于将多个视图模型映射到单个视图(here)的问题。我得到了一些很好的答案,但我仍然无法将我在那里学到的东西应用到我的特定情况。
简要概述:我想创建一个基础ItemViewModelBase类,它公开我的视图将绑定到的属性。然后我将创建两个特定的视图模型,PeopleViewModel和CarsViewModel。这两个都继承自ItemViewModelBase并实现适当的属性。现在,我希望能够创建一个视图,根据绑定的视图模型显示相应的信息。由于PeopleViewModel和CarsViewModel都公开了相同的属性,并且我希望这两个视图看起来相同,我只需要一个视图。
我之前提出的问题中的一个答案建议使用DataTemplate:
<DataTemplate DataType="{x:Type ItemViewModelBase}">
//some user control
</DataTemplate>
我不熟悉将DataTemplates与MVVM(以及一般的MVVM)一起使用,所以我有几个问题:
现在ItemViewModelBase是一个抽象类,我定义了相应的属性(ItemName,Items等)。我的Items属性是一个ObservableCollection:
public virtual ObservableCollection<???> Items { get; set; }
我会把什么作为集合类型?从此基类派生的类将具有不同的列表(Person,Car)。基本视图模型是放置属性的正确位置吗?我确实希望所有派生类都实现它,所以它似乎如此。让Person和Car扩展一些基础对象是没有意义的。
假设我不需要对我的观点进行任何自定义。在这种情况下我只需要一个视图。目前尚不清楚我将如何设置它。我应该为ItemViewModelBase创建一个DataTemplate还是用一个视图(用户控件)来表示它?现在我使用Unity来注册我的视图模型,并且在创建视图时,视图模型将被注入视图中。当我尝试创建视图时,如何区分不同的视图模型?
基本上,我不知道在使用DataTemplates时如何显示适当的视图。在我的应用程序中,我现在有一个窗口,其中包含一个定义如下的选项卡控件:
<Grid>
<TabControl TabStripPlacement="Left" ItemsSource="{Binding TabItems}"/>
</Grid>
TabControl的样式包含以下setter:
<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的单个视图。
将非常感谢任何示例代码/示例,显示基本视图模型类,扩展该基本视图模型的一些其他视图模型类,然后能够基于视图模型显示适当的视图(仅存在一般观点)。
答案 0 :(得分:0)
你在一个问题恕我直言。尝试使用或不使用DataTemplates使代码工作(如果需要,可以使其变得很糟糕),然后专注于您认为需要改进的代码的一个区域,并发布有关如何解决特定问题的问题。我开始输入一个答案,很快就变得过于复杂,无法表达总体建议。
我不确定你在关于DataTemplates的其他问题上得到了很好的建议。我也非常关心如何设置ConfigTabItem - 它似乎是一个父视图模型,它使用容器(直接,这不是一个好习惯)来解析视图,该视图可能也有自己的视图模型。这似乎是不必要的复杂。
无论如何,再次尝试将其提炼为几个有针对性的问题。在任何一个有用的情况下,我的原始答案在下面(未经编辑):
首先,我不确定我理解您在上一个讨论DataTemplates的问题中给出的答案。如果您将始终绑定到ItemViewModelBase,我不清楚为什么需要指定DataType(甚至是DataTemplate)。这并不是说使用DataTemplate是一个坏主意,但我不确定在这种情况下我是否看到它的必要性。
我也会说我不确定我是否也看到了继承的必要性。数据绑定在运行时工作,并且在根据VM类型切换DataTemplate之外(正如我所说,我认为你不需要),视图并不关心它绑定到什么,只要属性是它寻找是在运行时找到的。
因此,作为一般事项,我将从您的视图模型的一个具体实现开始。让它正确绑定,然后确定它可以抽象到基类或接口中的哪些部分 if 这是你想要采用的方法。这不是必需的,但可能有助于使绑定的要求更容易“强制执行” - 例如,使用基类或接口将限制您(或其他人)更改绑定所需的属性名称。
我会把什么作为收藏品 类型?派生自的类 这个基类会有所不同 列表(人,车)。是基本视图 建立合适的地方 属性?我确实想要所有派生的 似乎是实现它的类 所以。并且它没有意义 人和车扩展了一些基础 对象
如果要为VM使用基类或接口,并且希望集合成为其中的一部分,则它可以只是ObservableCollection<object>
类型。添加到其中的项目都需要具有与您在XAML中引用的属性名称相匹配的属性名称。因此,如果只需要一个视图,则不能拥有“PersonName”和“CarName”属性;你需要使用像“ItemName”这样更通用的东西(除非你将DataTemplates与DataTypes一起使用 - 这实际上是 有用的地方)。同样,您不需要需要每个集合项从基类型继承或实现公共接口,除非(再次)您希望在编译时强制执行。
答案 1 :(得分:0)
从Microsoft App Studio查看通用应用程序的架构。根据Microsofts App Studio,DataTemplates应该位于Views Directory下的DataTemplates子目录中。通用应用程序具有Windows UI和Windows Phone UI的此目录,因此它不在共享项目中,因为它们不是相同的。不要使用Converge PRISM架构。它设计完全错误!这不是用Windows和Windows Phone架构编写的,但他们称之为Converged。它本应完全重新设计,就像在微软App Studio中一样。不要寻找依赖注入它不在其中而不是需要它。大多数使用依赖注入来存根或伪接口。设计数据的DataContext现在可以很好地处理json数据,而依赖注入组件则过度。