DataBind到ObservableCollection,仅显示某个派生类的元素

时间:2015-02-07 17:40:02

标签: c# wpf xaml mvvm observablecollection

我正在使用MVVM模式在WPF中开发一个应用程序,并且遇到了一些可能有点独特的东西。

我有一个抽象类MapEntity,它表示可以在我的应用程序的绘图表面上显示的实体。其他类(如LineEntityTextEntity等)继承自MapEntity

要显示这些内容,我为每种类型创建一个ObservableCollection并将其绑定到我的XAML,后者获取每个实体的属性并显示它们。 (例如,创建一个包含TextEntity

的颜色和文本的文本框

一起管理这些实体感觉有点像黑客。如果我为每个实体都有一堆集合,我可以创建一个ObservableCollection<MapEntity>,并将所有实体添加到其中。这将使处理它们变得更容易,例如在用户拖动实体时检查它们的边界,或者通过MapEntity中定义的更新方法更新它们。标准继承的东西。

使用此技术时出现问题,是否有办法创建绑定到此单个集合的ItemsControl(而不是将每个ItemsControl绑定到TextEntity的集合,LineEntity等,但只显示某种类型的元素?

例如:

视图模型:

public ObvervableCollection<MapEntity> Entities { get; set; //OnPropertyChanged stuff}
...
Entities.Add(new LineEntity(...));
Entities.Add(new TextEntity(...));

因此,我将不同的MapEntities添加到单个集合中,而不是为每种类型添加多个集合。

查看:

使用单独的集合,我可以将每个ItemsControl项绑定到特定集合,但是使用一个Entities集合,我找不到一种方法来“过滤”某个类型的元素派生自MapEntity

所以不要这样做:

<ItemsControl ItemsSource="{Binding LineEntities}"> <!-- More Stuff -->  </ItemsControl>
 <ItemsControl ItemsSource="{Binding TextEntities}"> <!-- More Stuff -->  </ItemsControl>

我想这样做:

<ItemsControl ItemsSource="{Binding Entities WHERE type = LineEntity}"> <!-- More Stuff -->  </ItemsControl>
 <ItemsControl ItemsSource="{Binding Entities WHERE type = TextEntity}"> <!-- More Stuff -->  </ItemsControl>

(显然无效),但基本上我想从集合中“过滤”出所需的类型,通过不使用单独的集合,可以更轻松地在ViewModel中进行管理。 (由于这个原因,必须分别对每个操作进行操作)

我很确定这是不可能的,但我想如果有人通过XAML或ViewModel提出任何想法,我会问。

2 个答案:

答案 0 :(得分:2)

您可以查看CollectionViewSource类,并使用它的过滤功能来过滤类型。

好消息是它从您的基础ObservableCollection传播集合更改的事件。

答案 1 :(得分:2)

您可能已经知道ItemsControl会根据每个项目的类型自动选择正确的ItemTemplate

为从MapEntity派生的每个类型定义一个空的DataTemplate,如下所示,以便任何ItemsControl(没有明确设置其ItemTemplate),从这些资源中选择。

<Window.Resources>
    <DataTemplate DataType="{x:Type vm:TextEntity}">
    </DataTemplate>
    <DataTemplate DataType="{x:Type vm:LineEntity}">
    </DataTemplate>
</Window.Resources>

现在您需要为每个ItemsControl覆盖其中一个。

<ItemsControl ItemsSource="{Binding Entities}">
    <ItemsControl.Resources>
        <DataTemplate DataType="{x:Type vm:TextEntity}">
            <!-- Template for text entity -->
        </DataTemplate>
    </ItemsControl.Resources>
</ItemsControl>