Вам нужен второй класс для подгрупп, так что вы можете определить один шаблон данных для групп и один для подгрупп. Ваши классы моделей могут быть что-то вроде
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 () поможет вам определить, к какому конкретному типу относится выбранный элемент.