2014-01-20 26 views
1

我有一個TreeView的簡單應用程序,我希望顯示一個SHAPES層次結構。我使用的是MVVM,所以我有一個ViewModel,它具有ObservableCollection Shapes屬性。WPF TreeView - 從VM中的FLAT列表中篩選TreeViewItem源

ShapeVm是基類,有幾個Shape子類型(SquareVm,CircleVm,ArcVm等)。很基本的東西。 ShapeVm基類有一個叫做ShapeType的可精簡屬性(一個枚舉:enum {Square,Circle,Arc},每個ShapeVm子類提供了它的類型。

現在,你可以看到這是怎麼回事: TreeView,我需要的是這些形狀的等級顯示,'ShapeType'節點,以及每個節點包含該類型的形狀

所以,我嘗試了各種各樣的東西,像XAML,像CollectionViewSource,以提供一種由ShapeType進行分組的方法,它可以工作,但它只顯示列表中的EXIST項目和組。

我在TreeView中需要的是讓這些組節點顯示出來,無論他們是否有i或者不是。

如此,例如(在Windows'的DataContext綁定到ShapesViewModel,它具有‘形狀’屬性)

<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> 

現在,我已經擺弄我的視圖模型,在那裏我揭露的屬性,一個每個形狀類型的集合,從主要形狀集合中獲取其數據。我知道,ViewModels的工作應該是在那裏爲View提供服務,無論View需要做什麼工作。但我不想擁有大量的公共集合類型,每次需要與主Shapes集合「同步」時,每次都會發生更改等。它變得複雜。

我只想知道在XAML中是否有辦法說:「嘿,'矩形'節點,您必須只顯示'矩形',從Shapes集合中,ok。」。

幫助表示讚賞。

回答

0

我不確定XAML有可能限制每個子部分的類型,但一種解決方案是從Shapes枚舉的外部LINQ連接中獲取數據。

下面的類具有帶ShapeTypes和枚舉的Shapes,並且ShapesData屬性公開了使用下面的xaml可視化的LINQ外部聯接。

根據需要,此解決方案將爲您提供空組,其中沒有該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> 
+0

馬克 - 謝謝,看起來很有希望......會給它一個去看看會發生什麼。敬請關注 :-) – csharper