WPF TreeView-从VM中的平面列表筛选TreeView项目源
我有一个带有树状视图的简单应用程序,我想显示形状的层次结构。我使用的是MVVM,所以我有一个ViewModel,它具有ObservableCollection形状的属性 ShapeVm是基类,有几个形状子类型(SquareVm、CircleVm、ArcVm等)。非常基本的东西。ShapeVm基类有一个称为ShapeType(一个enum:enum{Square,Circle,Arc})的可重写属性,每个ShapeVm子类提供它是什么类型的形状 现在,您可以看到这一点:在树视图中,我所需要的只是这些形状的分层显示,带有“ShapeType”节点,每个节点都包含该类型的形状 因此,我在XAML中尝试了各种方法,比如CollectionViewSource,以提供一种按ShapeType分组的方法,这种方法很有效,但它只显示列表中存在的项和组 在树视图中,我需要的是显示那些组节点,无论它们是否有项目 因此,例如(Windows的DataContext绑定到ShapeViewModel,它具有“Shapes”属性)WPF TreeView-从VM中的平面列表筛选TreeView项目源,wpf,treeview,treeviewitem,Wpf,Treeview,Treeviewitem,我有一个带有树状视图的简单应用程序,我想显示形状的层次结构。我使用的是MVVM,所以我有一个ViewModel,它具有ObservableCollection形状的属性 ShapeVm是基类,有几个形状子类型(SquareVm、CircleVm、ArcVm等)。非常基本的东西。ShapeVm基类有一个称为ShapeType(一个enum:enum{Square,Circle,Arc})的可重写属性,每个ShapeVm子类提供它是什么类型的形状 现在,您可以看到这一点:在树视图中,我所需要的只是这
现在,我已经摆弄了我的ViewModel,在这里我公开了一个属性,一个集合,每种类型的形状,它从主形状集合中获取数据。我知道ViewModels的工作应该是在那里“服务”视图,无论视图需要做什么。但我不想有一大堆公共集合pes,每一个都需要在每次更改时以某种方式与主形状集合“同步”,等等。它变得复杂了
我只想知道,在XAML中,是否有一种方法可以说:“嘿,‘矩形’节点,您必须只显示‘矩形’(来自Shapes集合,好的)。
感谢您的帮助。我不确定XAML是否有可能限制每个小节中的类型,但一种解决方案是从形状枚举上的外部LINQ连接获取数据 下面的类具有具有ShapeType和枚举的形状,ShapesData属性公开使用下面的xaml可视化的LINQ外部联接 此解决方案将为您提供空组,其中不存在具有该形状类型的项目(如您所需),并且很容易应用于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;
}
}
}
公共类固定类型
{
公共枚举形状类型
{
圆圈
椭圆,
长方形
}
公共阶级形态
{
公共ShapeType ShapeType{get;set;}
}
公共可观察集合形状{get;set;}
公共固定类型()
{
这个。形状=
新可观测集合(
新[]
{
新形状(){ShapeType=ShapeType.Circle},新形状(){ShapeType=ShapeType.Ellipse},
新形状(){ShapeType=ShapeType.Ellipse}
});
}
公共IEnumerable形状数据
{
收到
{
var data=来自(ShapeType[])Enum.GetValues(typeof(ShapeType))中的e
在e上的形状中连接s等于s。形状类型为es
从es.DefaultIfEmpty()中的s开始
选择新的{ShapeType=e,Shape=s};
返回数据;
}
}
}
XAML
Mark-谢谢,看起来很有希望……我们将试一试,看看会发生什么。请继续关注:-)
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;
}
}
}
<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>