我有一个使用TreeView的简单应用程序,我想显示一个SHAPES层次结构。我正在使用MVVM,所以我有一个ViewModel,它具有ObservableCollection Shapes的属性。
ShapeVm是基类,有几种Shape子类型(SquareVm,CircleVm,ArcVm等)。很基本的东西。 ShapeVm基类具有一个名为ShapeType的overidable属性(枚举:enum {Square,Circle,Arc},每个ShapeVm子类提供它的Shape类型。
现在,你可以看到它的发展方向:在TreeView中,我需要的是这些形状的分层显示,带有'ShapeType'节点,每个节点都包含该类型的形状。
所以,我已经在XAML中尝试了各种各样的东西,比如CollectionViewSource,它提供了一种按ShapeType分组的方法,它可以工作,但它只显示列表中存在的项目和组。
在TreeView中,我需要显示那些组节点,无论它们是否有项目。
所以,例如(Windows的DataContext绑定到ShapesViewModel,它具有'Shapes'属性)
<TreeView>
<!-- Itemtemplate omitted here -->
<TreeViewItem Header="Rectangles" IsExpanded="true" ItemsSource="{Binding Shapes}">
</TreeViewItem>
<TreeViewItem Header="Squares" IsExpanded="true" ItemsSource="{Binding Shapes}">
</TreeViewItem>
<TreeViewItem Header="Circles" IsExpanded="true" ItemsSource="{Binding Shapes}">
</TreeViewItem>
</TreeView>
现在,我摆弄了我的ViewModel,在那里我展示了每个Type类型的属性,一个集合,它从主要的形状集合中获取数据。我知道ViewModels的工作应该在那里“提供”View,无论View需要做什么工作。但是我不想拥有一大堆公共Collection类型,每个类型都需要在每次更改时以某种方式与主Shapes集合“同步”。它变得复杂。
我只是想知道在XAML中是否有办法说:“嘿,'矩形'节点,你必须只显示'矩形',来自Shapes集合,好吧。”
帮助表示赞赏。
答案 0 :(得分:0)
我不确定XAML是否可以限制每个子部分中的类型,但一种解决方案是从Shapes枚举的外部LINQ连接中获取数据。
下面的类包含Shapes with ShapeTypes和一个枚举,ShapesData属性公开了一个LINQ外连接,可以使用下面的xaml显示。
此解决方案将为您提供空组,其中不存在具有该ShapeType的项目,并且可以轻松应用于TreeView解决方案。
public class FixedTypes
{
public enum ShapeType
{
Circle,
Ellipse,
Rectangle
}
public class Shape
{
public ShapeType ShapeType { get; set; }
}
public ObservableCollection<Shape> Shapes { get; set; }
public FixedTypes()
{
this.Shapes =
new ObservableCollection<Shape>(
new[]
{
new Shape() { ShapeType = ShapeType.Circle }, new Shape() { ShapeType = ShapeType.Ellipse },
new Shape() { ShapeType = ShapeType.Ellipse }
});
}
public IEnumerable ShapesData
{
get
{
var data = from e in (ShapeType[])Enum.GetValues(typeof(ShapeType))
join s in Shapes on e equals s.ShapeType into es
from s in es.DefaultIfEmpty()
select new { ShapeType = e, Shape = s};
return data;
}
}
}
XAML
<Grid>
<Grid.Resources>
<CollectionViewSource x:Key="fixedTypes"
Source="{Binding ShapesData}">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="ShapeType" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
</Grid.Resources>
<ItemsControl ItemsSource="{Binding Source={StaticResource fixedTypes}}">
<ItemsControl.GroupStyle>
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<GroupBox Header="{Binding Name}">
<ItemsPresenter />
</GroupBox>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</ItemsControl.GroupStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Shape.ShapeType}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>