简体   繁体   English

WPF隐式datatemplate与observablecollection

[英]WPF implicit datatemplate with observablecollection

I'm new to WPF and using MVVM. 我是WPF新手并使用MVVM。 I have a view in which I want to display different content according to what a user selects on a menu. 我有一个视图,我想根据用户在菜单上选择的内容显示不同的内容。 One of those things is another user control Temp which has a view model (TempVM) so I am doing this: 其中一个是另一个用户控件Temp,它有一个视图模型(TempVM)所以我这样做:

<ContentControl Content="{Binding Path=TempVM}"/>

and TempVM (of type TempViewModel)is null until the user clicks a button. 并且TempVM(类型为TempViewModel)在用户单击按钮之前为空。 Its data template is this 它的数据模板是这样的

 <DataTemplate DataType="{x:Type vm:TempViewModel}">
        <view:Temp />
    </DataTemplate>

That's fine, but the other thing I want to do is show a listbox when a user clicks a different menu item. 这没关系,但我要做的另一件事是当用户点击不同的菜单项时显示一个列表框。 So I am trying to do 所以我想做

<ContentControl Content="{Binding Path=Missions}"/>

(Missions is an observable collection of MissionData) and trying to template it like this: (任务是一个可观察的MissionData集合)并试图模仿它:

 <DataTemplate DataType="{x:Type ObservableCollection(MissionData)}">
        <StackPanel>
            <ListBox ItemsSource="{Binding}" SelectedItem="{Binding Path=MissionData, Mode=TwoWay}" DisplayMemberPath="MissionName" SelectedValuePath="MissionId" />
            <Button Content="Go"/>
        </StackPanel>
    </DataTemplate>

But the compiler doesn't like the type reference. 但是编译器不喜欢类型引用。 If I try doing it by giving the template a key and specifying that key in the ContentControl it works but obviously I see the ListBox and button when there's no Missions. 如果我尝试通过给模板一个键并在ContentControl中指定该键它可以工作但显然我看到ListBox和按钮没有任务时。 Obviously I could make a user control and viewmodel and follow the same pattern as I did for the TempVM but it seems over the top. 显然,我可以创建一个用户控件和视图模型,并遵循与TempVM相同的模式,但它似乎超越了顶部。 Am I going the right way about this and what do I need to do? 我是否正确地对待这个问题,我需要做什么?

From what i see is that you try to use a Collection as a dataobject which is in my opinion bad practice. 从我看到的是你尝试使用Collection作为数据对象,这在我看来是不好的做法。 Having a DataTemplate for a collection is also problematic, like you already have witnessed. 拥有DataTemplate的集合也存在问题,就像您已经见过的那样。 I would advice you to use a ViewModel for your missions collection. 我建议你使用ViewModel作为你的任务集合。

class MissionsSelectionViewModel
{
    public ObservableCollection<Mission> Misssions;
    public MissionData SelectedMission;
    public ICommand MissionSelected;
}

and modify your datatemplate to 并将您的datatemplate修改为

<DataTemplate DataType="{x:Type MissionsSelectionViewModel}">
    <StackPanel>
        <ListBox ItemsSource="{Binding Missions}" SelectedItem="{Binding Path=MissionData, Mode=TwoWay}" DisplayMemberPath="MissionName" SelectedValuePath="MissionId" />
        <Button Content="Go" Command="{Binding MissionSelected}/>
    </StackPanel>
</DataTemplate>

If I were to follow your pattern of implicit templates, I would derive a custom non-generic collection MissionDataCollection from ObservableCollection<MissionData> and use it to keep MissionData items. 如果我要遵循隐式模板的模式,我将从ObservableCollection<MissionData>派生一个自定义的非泛型集合MissionDataCollection ,并使用它来保存MissionData项目。 Then I would simply reference that collection in DataType . 然后我只想在DataType引用该集合。 This solution gives other advantages like events aggregation over the collection that are useful. 此解决方案提供了其他优点,例如有用的集合上的事件聚合。

However, it seems to me that the best solution is the following. 但是,在我看来,最好的解决方案如下。

  1. Add a IsMissionsListVisible property to your VM. IsMissionsListVisible属性添加到VM。
  2. Bind the Visibility property of the ContentControl showing the list to the IsMissionsListVisible property. 将显示列表的ContentControlVisibility属性绑定到IsMissionsListVisible属性。
  3. Use a keyed DataTemplate resource. 使用键控的DataTemplate资源。
  4. Implement the logic that determines if IsMissionsListVisible . 实现确定IsMissionsListVisible的逻辑。 Supposedly it should be true when there is at least one mission in the selected item. 据推测,当所选项目中至少有一个任务时,它应该是真的。 But the logic may be more complex. 但逻辑可能更复杂。

I would do it this way. 我会这样做的。 In fact, I do it this way usually, and it gives several benefits. 事实上,我通常这样做,它有几个好处。 The most important is that I can explicitly control the logic of content visibility in various situations (eg async content refresh). 最重要的是我可以在各种情况下明确控制内容可见性的逻辑(例如异步内容刷新)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM