如何使用wpf中的数据模板在列表框中显示分层数据
本文关键字:数据 列表 分层 显示 何使用 wpf | 更新日期: 2023-09-27 18:25:09
我有一个分组和子分组的分层集合,比如:
- 第1组
- 子组1
- 子组2
- 第2组
- 子组1
我想做的是在列表框中显示这个分层数据。我尝试创建不同的数据模板,我可以显示子组,但无法显示组名。
我用于此目的的类是这样的:
public class Groups
{
public string Group {get; set;}
public List<string> SubGroup {get; set;}
}
我将列表绑定到列表框的ItemsSource。我需要的是一个数据模板,可以用来分层显示这些数据。
我不能使用其他控件,我必须使用列表框。
编辑:通过查看Desty提供的建议,我能够使用此数据模板显示值
<DataTemplate x:Key="SubGroups">
<StackPanel>
<Label Content="{Binding Path=Group}" />
<ItemsControl Margin="30,0,0,0" ItemsSource="{Binding SubGroup}" />
</StackPanel>
</DataTemplate>
现在的问题是,我无法从列表框中选择单独的子组。它选择了完整的ListBoxItem,而我无法选择单独的子组。
您需要的是SubGroups的第二个类,这样您就可以为Groups和SubGroups定义一个DataTemplate。您的模型类可能类似
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中,您可以为每种类型定义一个DataTemplate:
<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编辑后):
如果子组项目也可以点击,那么(IMHO)从列表框的角度来看,组和子组之间不会有区别。所以我的变通办法是:
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()可以帮助您找出所选项目的具体类型。