需要帮助制作一个嵌套的' WPF ItemsControl

时间:2015-08-28 00:07:26

标签: wpf mvvm

任何人都可以告诉我试图制作一个“嵌套”的东西。 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.
  3. 现在我有了这个XAML,它不起作用:

    <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为什么我想使用这样的模型 - 我需要功能来分割任何&#34; Visual&#34;垂直或水平,代码意味着 - 改变一个来源PlateItem:&#34; Child&#34; -type to&#34; Container&#34; -type with 2 new children

1 个答案:

答案 0 :(得分:1)

您需要调整DatatemplatePlateItemDouble,删除其ItemTemplate,而不是使用相同的ItemTemplateSelector。因此,它会递归地将DatatemplatePlateItemDouble应用于所有带子项的后代。

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

您还需要更改/删除此行,这将导致无限递归。

  item_Main.Children.Add(item_Main);

一旦你这样做,你应该得到 The produced image