2015-08-28 108 views
0

任何人都可以請告訴我想要嘗試做一個'嵌套的'WPF ItemsControl ...如果它甚至可以按我想要的方式工作。 我有這個數據模型:需要幫助使'嵌套'的WPF ItemsControl

public class PlateItem 
{ 
    public Guid ID { get; set; } 
    public string Type { get; set; } 
    public string Caption { get; set; } 
    public int GridRow { get; set; } 
    public int GridColumn { get; set; } 

    // 0 or 2 Children 
    public ObservableCollection<PlateItem> Children { get; set; } 
} 

private void Initialize() 
{ 
    ObservableCollection<PlateItem> collection = new ObservableCollection<PlateItem>(); 

    // Type = "Child" - Caption should be displayed 
    // Type = "Container" - Caption should not be displayed. Its Children of type "Visual" Captions should be displayed 

    PlateItem item_Main = new PlateItem() { Type = "Container", Caption = "ZERO", GridRow = 0, GridColumn = 0, ID = Guid.NewGuid(), Children = new ObservableCollection<PlateItem>() }; 
    PlateItem item_Main_A = new PlateItem() { Type = "Child", Caption = "ONE", GridRow = 0, GridColumn = 0, ID = Guid.NewGuid(), Children = new ObservableCollection<PlateItem>() }; 
    PlateItem item_Main_B = new PlateItem() { Type = "Container", Caption = "TWO", GridRow = 1, GridColumn = 0, ID = Guid.NewGuid(), Children = new ObservableCollection<PlateItem>() }; 
    PlateItem item_Main_B_1 = new PlateItem() { Type = "Child", Caption = "THREE", GridRow = 0, GridColumn = 0, ID = Guid.NewGuid(), Children = new ObservableCollection<PlateItem>() }; 
    PlateItem item_Main_B_2 = new PlateItem() { Type = "Child", Caption = "FOUR", GridRow = 1, GridColumn = 0, ID = Guid.NewGuid(), Children = new ObservableCollection<PlateItem>() }; 

    item_Main_B.Children.Add(item_Main_B_1); 
    item_Main_B.Children.Add(item_Main_B_2); 

    item_Main.Children.Add(item_Main_A); 
    item_Main.Children.Add(item_Main_B); 

    collection.Add(item_Main); 

    this.PlateItemsSource = collection; 
} 

我需要一個嵌套的控制,以便:

  1. 如果PlateItem沒有孩子 - 與 PlateItem.Caption顯示一個文本框
  2. 如果PlateItem有孩子(最多2個) - 顯示一個網格 與兩個孩子使用規則1.

現在我有這個XA ML,這不工作:

<UserControl.Resources> 

    <!-- ************************************************** --> 
    <h:TemplateselectorPlateItem x:Key="TemplateselectorPlateItem"/> 

    <!-- should display PlateItems that don't have Children --> 
    <DataTemplate x:Key="DatatemplatePlateItemSingle"> 
     <TextBox Background="Green" Margin="20" 
       Text="{Binding Path=Caption, Mode=TwoWay}" /> 
    </DataTemplate> 

    <!-- should display PlateItems that has Children  --> 
    <DataTemplate x:Key="DatatemplatePlateItemDouble"> 
     <ItemsControl ItemsSource="{Binding Path=Children}" 
         ItemTemplate="{StaticResource DatatemplatePlateItemSingle}"> 

      <ItemsControl.ItemContainerStyle> 
       <Style> 
        <Style.Setters> 
         <Setter Property="Grid.Row" Value="{Binding Path=GridRow}"/> 
         <Setter Property="Grid.Column" Value="{Binding Path=GridColumn}"/> 
        </Style.Setters> 
       </Style> 
      </ItemsControl.ItemContainerStyle> 

      <ItemsControl.ItemsPanel> 
       <ItemsPanelTemplate> 
        <Grid> 
         <Grid.RowDefinitions> 
          <RowDefinition Height="Auto"/> 
          <RowDefinition Height="Auto"/> 
         </Grid.RowDefinitions> 
         <Grid.ColumnDefinitions> 
          <ColumnDefinition Width="Auto"/> 
          <ColumnDefinition Width="Auto"/> 
         </Grid.ColumnDefinitions> 
        </Grid> 
       </ItemsPanelTemplate> 
      </ItemsControl.ItemsPanel> 
     </ItemsControl> 
    </DataTemplate> 

</UserControl.Resources> 

<ItemsControl ItemsSource="{Binding Path=PlateItemsSource}" 
       ItemTemplateSelector="{StaticResource TemplateselectorPlateItem}"> 
</ItemsControl> 

代碼爲TemplateSelector:

public class TemplateselectorPlateItem : DataTemplateSelector 
{ 
    public override DataTemplate SelectTemplate(object item, DependencyObject container) 
    { 
     FrameworkElement element = container as FrameworkElement; 

     if (element != null && item != null && item is PlateItem) 
     { 
      PlateItem plateItem = item as PlateItem; 

      if(plateItem.Children.Count == 0) 
      { 
       return element.FindResource("DatatemplatePlateItemSingle") as DataTemplate; 
      } 
      else 
      { 
       return element.FindResource("DatatemplatePlateItemDouble") as DataTemplate; 
      } 
     } 

     return null; 
    } 
} 
什麼我試着去實現 http://www.trinitytilesupply.com/pattern2.jpg爲什麼我想用這樣的模型

非常粗糙的視覺表現 - 我需要的功能分裂任何「視覺」垂直或水平,在代碼,這將意味着 - 更改來源PlateItem:「兒童」類型爲「容器」型與2個新的兒童

+0

我非常喜歡'DataTriggers'而不是'DataTemplateSelector'動態切換模板。當屬性在運行時發生變化時,Selector的代碼不會100%運行。 –

+0

感謝您的回覆,但我無法看到DataTrigger如何以及在哪裏適合 - 在哪個部分?你能解釋更多嗎? –

+0

我大概理解你的意思,將需要嘗試 –

回答

1

你需要調整DatatemplatePlateItemDouble,刪除它的ItemTemplate,而不是相同的ItemT emplateSelector。所以它會遞歸地將DatatemplatePlateItemDouble應用於所有帶子的後代。

<DataTemplate x:Key="DatatemplatePlateItemDouble"> 
     <ItemsControl ItemsSource="{Binding Path=Children}" 
         ItemTemplateSelector="{StaticResource TemplateselectorPlateItem}" > 
    ... 

您還需要更改/刪除此行,這將導致無限遞歸。

item_Main.Children.Add(item_Main); 

一旦你這樣做,你應該得到 The produced image

+0

謝謝,這是我需要的輸出...但是,我仍然不能讓它像你一樣工作 - 你可以分享你的修改後的代碼到[email protected]嗎? –

+0

在我的代碼中發現一個錯誤,編輯我的問題,現在工作正常。謝謝! –

+0

我很高興,幫助。 –