WPF TreeView-从VM中的平面列表筛选TreeView项目源

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子类提供它是什么类型的形状 现在,您可以看到这一点:在树视图中,我所需要的只是这

我有一个带有树状视图的简单应用程序,我想显示形状的层次结构。我使用的是MVVM,所以我有一个ViewModel,它具有ObservableCollection形状的属性

ShapeVm是基类,有几个形状子类型(SquareVm、CircleVm、ArcVm等)。非常基本的东西。ShapeVm基类有一个称为ShapeType(一个enum:enum{Square,Circle,Arc})的可重写属性,每个ShapeVm子类提供它是什么类型的形状

现在,您可以看到这一点:在树视图中,我所需要的只是这些形状的分层显示,带有“ShapeType”节点,每个节点都包含该类型的形状

因此,我在XAML中尝试了各种方法,比如CollectionViewSource,以提供一种按ShapeType分组的方法,这种方法很有效,但它只显示列表中存在的项和组

在树视图中,我需要的是显示那些组节点,无论它们是否有项目

因此,例如(Windows的DataContext绑定到ShapeViewModel,它具有“Shapes”属性)


现在,我已经摆弄了我的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>