Как я могу отображать иерархические данные в поле списка, используя шаблоны данных в wpf - PullRequest
0 голосов
/ 20 февраля 2012

У меня есть иерархическая коллекция групп и подгрупп, например:

  • Группа 1
    • Подгруппа1
    • Подгруппа2
  • Group 2
    • SubGroup1

Я хочу отобразить эти иерархические данные в списке.Я пытался создать разные шаблоны данных, и я могу показать подгруппы, но не могу отобразить имена групп.

Класс, который я использую для этой цели, выглядит примерно так:

public class Groups
{
public string Group {get; set;}
public List<string> SubGroup {get; set;}
}

Я связываю List с ItemsSource списка.Мне нужен шаблон данных, который я могу использовать для иерархического отображения этих данных.

Я не могу использовать другой элемент управления для этого, я должен использовать список.

Редактировать: Глядя на предложение, предоставленное Desty, я могу отобразить значения, используя этот шаблон данных

<DataTemplate x:Key="SubGroups">
  <StackPanel>
    <Label Content="{Binding Path=Group}" />
    <ItemsControl Margin="30,0,0,0" ItemsSource="{Binding SubGroup}" />
  </StackPanel>
</DataTemplate>

Проблема в том, что яневозможно выбрать отдельные подгруппы из списка.Он выбирает полный ListBoxItem, и я не могу выбрать отдельные подгруппы.

1 Ответ

1 голос
/ 21 февраля 2012

Вам нужен второй класс для подгрупп, так что вы можете определить один шаблон данных для групп и один для подгрупп. Ваши классы моделей могут быть что-то вроде

public class Group {
  public string Name { get; set; }
  public List<SubGroup> SubGroups { get; set; }
  public Group(string name) { this.Name = name; }
}

public class SubGroup {
  public string Name { get; set; }
  public SubGroup(string name) { this.Name = name; }
}

В WPF вы можете определить шаблон данных для каждого типа:

<Window.Resources>
  <DataTemplate DataType="{x:Type local:SubGroup}">
    <StackPanel Orientation="Horizontal">
      <TextBlock Text=" +-- "/><TextBlock Text="{Binding Name}"/>
    </StackPanel>
  </DataTemplate>
  <DataTemplate DataType="{x:Type local:Group}">
    <StackPanel>
      <TextBlock Text="{Binding Name}"/>
      <ItemsControl ItemsSource="{Binding SubGroups}"/>
     </StackPanel>
  </DataTemplate>
</Window.Resources>
<Grid>
  <ListBox ItemsSource="{Binding}" />
</Grid>

Редактировать (после просмотра редактирования Bhattis):

Если элементы подгруппы также должны быть кликабельными, то (ИМХО) не может быть разницы между группой и подгруппой с точки зрения ListBox. Так что мое предположение обходного пути:

public class Groups {
  public string Group { get; set; }
} 

В окне WPF

<ListBox ItemsSource="{Binding}">
  <ListBox.ItemTemplate>
    <DataTemplate>
      <StackPanel>
        <Label Content="{Binding Path=Group}" />
      </StackPanel>
    </DataTemplate>
  </ListBox.ItemTemplate>
</ListBox>

И в файле кода WPF:

public MainWindow() {
  InitializeComponent();
  Groups g1 = new Groups() { Group = "Parent 1" };
  Groups s1 = new Groups() { Group = "   Sub 1" };
  Groups s2 = new Groups() { Group = "   Sub 2" };
  Groups g2 = new Groups() { Group = "Parent 2" };
  Groups s3 = new Groups() { Group = "   Sub 1" };
  Groups s4 = new Groups() { Group = "   Sub 2" };
  this.DataContext = new List<Groups>() { g1, s1, s2, g2, s3, s4 };
}

Здесь каждая подгруппа - не что иное, как группа, поэтому каждая «строка» кликабельна. Важно то, что последовательность списка имеет большое значение, потому что структура больше не в модели.

Если вы должны реагировать по-разному, в зависимости от того, щелкнул ли пользователь группой или подгруппой, вы можете построить иерархию наследования в вашей модели и поместить соответствующие объекты в DataContext. Чтобы привести вас в правильном направлении, я имею в виду что-то вроде

public abstract class AbstractGroup {
    public string Name { get; set; }
    public AbstractGroup(string name) { this.Name = name; }
}
public class Group : AbstractGroup {
    public Group(string name) : base(name) {}
}
public class SubGroup : AbstractGroup {
    public SubGroup(string name) : base(name) {}
} 

Код-за:

    InitializeComponent();
    AbstractGroup g1 = new Group("Parent 1");
    AbstractGroup s1 = new SubGroup("  Sub 1");
    AbstractGroup s2 = new SubGroup("   Sub 2");
    AbstractGroup g2 = new Group("Parent 2");
    AbstractGroup s3 = new SubGroup("   Sub 1");
    AbstractGroup s4 = new SubGroup("   Sub 2");
    this.DataContext = new List<AbstractGroup>() { g1, s1, s2, g2, s3, s4 };

XAML:

<ListBox ItemsSource="{Binding}">
  <ListBox.ItemTemplate>
    <DataTemplate>
      <StackPanel>
        <Label Content="{Binding Path=Name}" />
      </StackPanel>
    </DataTemplate>
  </ListBox.ItemTemplate>
</ListBox>

Поскольку вы можете получить выбранный объект в DataContext, typeof () поможет вам определить, к какому конкретному типу относится выбранный элемент.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...