具有混合类型的 TreeView HierarchicalDataTemplate
TreeView HierarchicalDataTemplate with mixed types
我实际上正在开发我的第一个 WPF 应用程序,它必须在具有分层数据的树视图中显示我的计算机的所有组件。
从昨天开始,我遇到了一个小问题,我阅读了大量的 treeview 绑定示例,但我没有成功绑定多个类型...
它必须看起来像这样:
我的机器(0级)
-----键盘⬇️(1级)
--------键盘1⬇️(2级)
--------键盘2⬇️(2级)
-----OS⬇️(1级)
-----CPU⬇️(1级)
--------CPU1⬇️(2级)
--------CPU2⬇️(2级)
-----VideoCard⬇️(1级)
------------VideoCard1⬇️(level 2)
------------VideoCard2⬇️(2级)
我有一个包含所有组件设备的视图模型:
DeviceInfo.cs :
public class DeviceInfo
{
public string ComputerName { get; set; }
public Bios Bios { get; set; }
public ComputerSystem ComputerSystem { get; set; }
public List<Keyboard> Keyboards { get; set; }
public OperatingSystem OperatingSystem { get; set; }
public List<Processor> Processors { get; set; }
public List<VideoCard> VideoCards { get; set; }
}
每个组件包含特定的属性,例如Keyboard.cs:
public class Keyboard
{
public string Description { get; set; }
public string DeviceID { get; set; }
}
我为我的树视图尝试了类似的方法,我在 Mainwindow 中像这样绑定数据:
DeviceTree.ItemsSource = deviceInfos;
MainWindow.xaml :
<TreeView Margin="10" BorderThickness="2" BorderBrush="Black" Name="DeviceTree">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="x:Type data:DeviceInfo" ItemsSource="{Binding Keyboards}">
<TextBlock Text="{Binding Description}"></TextBlock>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="x:Type data:DeviceInfo" ItemsSource="{Binding OS}">
<TextBlock Text="{Binding Version}"></TextBlock>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="x:Type data:DeviceInfo" ItemsSource="{Binding VideoCard}">
<TextBlock Text="{Binding SerialNumber}"></TextBlock>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
实际上它在我的树视图模板中看起来像这样:
"Model.DeviceInfo"
每个link类似的例子都会对我有所帮助。
提前致谢
当 WPF 不知道如何在视图上显示您的模型时,通常会发生这种情况。
在您的源代码中,您已经定义了在 TextBox 中显示模型的每个属性的模板。但是您还没有将它们应用到您的视图中。
所以它只显示模型的默认 ToString()。这就是为什么您只看到文本 "Model.DeviceInfo".
以下link会对您有所帮助。
一个HierarchicalDataTemplate
只支持一个child属性。为同一类型定义三个模板是没有意义的。无论如何,只有它们可以在运行时应用。
你应该做的是将你的 DeviceInfo
class 转换成一个 data-binding 友好的视图模型 class,它有一个 child 属性:
public class Item
{
public string Header { get; set; }
public IEnumerable<Item> Children { get; set; }
}
然后您将 ItemsSource
属性 绑定到四个 Item
根 objects 的 IEnumerable<Item>
,即 1 级键盘,OS、CPU 和 VideoCard 节点。
还要注意将 DataType
属性 设置为 XAML 中的实际类型的语法:
<TreeView Margin="10" BorderThickness="2" BorderBrush="Black" Name="DeviceTree">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:Item}" ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Header}" />
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
编辑:
如果级别总数不是动态的,即您总是有两个级别,您可以设置或绑定 ItemsSource
属性 到 new List<DeviceInfo>(1) { deviceInfos }
并添加"static" 根级别到 TreeView
在您的 XAML 标记中明确:
<TreeView Margin="10" BorderThickness="2" BorderBrush="Black" Name="DeviceTree">
<TreeViewItem Header="Keyboards" ItemsSource="{Binding Keyboards}">
<TreeViewItem.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Description}" />
</DataTemplate>
</TreeViewItem.ItemTemplate>
</TreeViewItem>
<TreeViewItem Header="Operating Systems" ItemsSource="{Binding OperatingSystem}">
<TreeViewItem.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Version}" />
</DataTemplate>
</TreeViewItem.ItemTemplate>
</TreeViewItem>
<!-- + TreeViewItems for Processors and VideoCards -->
</TreeView>
要制作你想要的东西,你只需将 TreeViewItem 放在你的主 TreeView 中。如果你想更上一层楼,你只需要添加一个带有 TreeViewItem 的 ItemTemplate。我给你一个简单对象(Bios)的例子,然后是一个对象列表(键盘)。
TreeView 的 ItemSources 是 DeviceInfo 的列表。
xaml :
<TreeView x:Name="MyTreeView">
<TreeView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TreeViewItem Header="{Binding ComputerName}">
<TreeViewItem.Items>
<TreeViewItem Header="Bios">
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Bios.Description}"/>
<TextBlock Text="{Binding Bios.Name}"/>
<TextBlock Text="{Binding Bios.Version}"/>
</StackPanel>
</TreeViewItem>
<TreeViewItem Header="Keyboard" ItemsSource="{Binding Keyboards}">
<TreeViewItem.ItemTemplate>
<DataTemplate>
<TreeViewItem Header="{Binding DeviceID}">
<TextBlock Text="{Binding Description}"/>
</TreeViewItem>
</DataTemplate>
</TreeViewItem.ItemTemplate>
</TreeViewItem>
</TreeViewItem.Items>
</TreeViewItem>
</StackPanel>
</DataTemplate>
</TreeView.ItemTemplate>
</TreeView>
我实际上正在开发我的第一个 WPF 应用程序,它必须在具有分层数据的树视图中显示我的计算机的所有组件。
从昨天开始,我遇到了一个小问题,我阅读了大量的 treeview 绑定示例,但我没有成功绑定多个类型...
它必须看起来像这样:
我的机器(0级)
-----键盘⬇️(1级)
--------键盘1⬇️(2级)
--------键盘2⬇️(2级)
-----OS⬇️(1级)
-----CPU⬇️(1级)
--------CPU1⬇️(2级)
--------CPU2⬇️(2级)
-----VideoCard⬇️(1级)
------------VideoCard1⬇️(level 2)
------------VideoCard2⬇️(2级)
我有一个包含所有组件设备的视图模型:
DeviceInfo.cs :
public class DeviceInfo
{
public string ComputerName { get; set; }
public Bios Bios { get; set; }
public ComputerSystem ComputerSystem { get; set; }
public List<Keyboard> Keyboards { get; set; }
public OperatingSystem OperatingSystem { get; set; }
public List<Processor> Processors { get; set; }
public List<VideoCard> VideoCards { get; set; }
}
每个组件包含特定的属性,例如Keyboard.cs:
public class Keyboard
{
public string Description { get; set; }
public string DeviceID { get; set; }
}
我为我的树视图尝试了类似的方法,我在 Mainwindow 中像这样绑定数据:
DeviceTree.ItemsSource = deviceInfos;
MainWindow.xaml :
<TreeView Margin="10" BorderThickness="2" BorderBrush="Black" Name="DeviceTree">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="x:Type data:DeviceInfo" ItemsSource="{Binding Keyboards}">
<TextBlock Text="{Binding Description}"></TextBlock>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="x:Type data:DeviceInfo" ItemsSource="{Binding OS}">
<TextBlock Text="{Binding Version}"></TextBlock>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="x:Type data:DeviceInfo" ItemsSource="{Binding VideoCard}">
<TextBlock Text="{Binding SerialNumber}"></TextBlock>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
实际上它在我的树视图模板中看起来像这样:
"Model.DeviceInfo"
每个link类似的例子都会对我有所帮助。 提前致谢
当 WPF 不知道如何在视图上显示您的模型时,通常会发生这种情况。 在您的源代码中,您已经定义了在 TextBox 中显示模型的每个属性的模板。但是您还没有将它们应用到您的视图中。
所以它只显示模型的默认 ToString()。这就是为什么您只看到文本 "Model.DeviceInfo".
以下link会对您有所帮助。
一个HierarchicalDataTemplate
只支持一个child属性。为同一类型定义三个模板是没有意义的。无论如何,只有它们可以在运行时应用。
你应该做的是将你的 DeviceInfo
class 转换成一个 data-binding 友好的视图模型 class,它有一个 child 属性:
public class Item
{
public string Header { get; set; }
public IEnumerable<Item> Children { get; set; }
}
然后您将 ItemsSource
属性 绑定到四个 Item
根 objects 的 IEnumerable<Item>
,即 1 级键盘,OS、CPU 和 VideoCard 节点。
还要注意将 DataType
属性 设置为 XAML 中的实际类型的语法:
<TreeView Margin="10" BorderThickness="2" BorderBrush="Black" Name="DeviceTree">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:Item}" ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Header}" />
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
编辑:
如果级别总数不是动态的,即您总是有两个级别,您可以设置或绑定 ItemsSource
属性 到 new List<DeviceInfo>(1) { deviceInfos }
并添加"static" 根级别到 TreeView
在您的 XAML 标记中明确:
<TreeView Margin="10" BorderThickness="2" BorderBrush="Black" Name="DeviceTree">
<TreeViewItem Header="Keyboards" ItemsSource="{Binding Keyboards}">
<TreeViewItem.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Description}" />
</DataTemplate>
</TreeViewItem.ItemTemplate>
</TreeViewItem>
<TreeViewItem Header="Operating Systems" ItemsSource="{Binding OperatingSystem}">
<TreeViewItem.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Version}" />
</DataTemplate>
</TreeViewItem.ItemTemplate>
</TreeViewItem>
<!-- + TreeViewItems for Processors and VideoCards -->
</TreeView>
要制作你想要的东西,你只需将 TreeViewItem 放在你的主 TreeView 中。如果你想更上一层楼,你只需要添加一个带有 TreeViewItem 的 ItemTemplate。我给你一个简单对象(Bios)的例子,然后是一个对象列表(键盘)。 TreeView 的 ItemSources 是 DeviceInfo 的列表。
xaml :
<TreeView x:Name="MyTreeView">
<TreeView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TreeViewItem Header="{Binding ComputerName}">
<TreeViewItem.Items>
<TreeViewItem Header="Bios">
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Bios.Description}"/>
<TextBlock Text="{Binding Bios.Name}"/>
<TextBlock Text="{Binding Bios.Version}"/>
</StackPanel>
</TreeViewItem>
<TreeViewItem Header="Keyboard" ItemsSource="{Binding Keyboards}">
<TreeViewItem.ItemTemplate>
<DataTemplate>
<TreeViewItem Header="{Binding DeviceID}">
<TextBlock Text="{Binding Description}"/>
</TreeViewItem>
</DataTemplate>
</TreeViewItem.ItemTemplate>
</TreeViewItem>
</TreeViewItem.Items>
</TreeViewItem>
</StackPanel>
</DataTemplate>
</TreeView.ItemTemplate>
</TreeView>