如何正确地将对象绑定到 Treeview
How to Properly Bind Object(s) to a Treeview
我一直在自学 C#,一直想编写一个使用树视图的 WPF 应用程序。不过,我花了很多时间弄清楚如何让数据绑定与它一起工作。
有人可以告诉我哪里出错了吗?在这一点上,我只是想得到一些东西,任何东西都可以在树中显示。我发现的显示如何使用 treeview 的资源让我很困惑。
提前感谢您的宝贵时间
编辑: 感谢您的回复。将 ItemSource = {Cars} 添加到树视图中已经引入了我实例化的两辆车的 Make。我如何着手使汽车可以扩展以显示功能列表?我会尝试自己解决这个问题,但此时任何帮助都将不胜感激,因为我对这个问题感到有点沮丧。
Cars.cs
using System;
using System.Collections.Generic;
namespace TreeViewTest
{
public class Cars
{
public List<Car> CarCollection { get; set; }
}
public class Car
{
public String Make { get; set; }
public String Model { get; set; }
public int Year { get; set; }
public List<String> Features { get; set; }
}
}
MainWindowViewModel.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace TreeViewTest
{
public class MainWindowViewModel : INotifyPropertyChanged
{
private List<Car> _Cars;
public List<Car> Cars
{
get { return _Cars; }
set
{
if (_Cars == value)
{
return;
}
_Cars = value;
NotifyPropertyChanged();
}
}
public Car _Car;
public Car Car
{
get { return _Car; }
set
{
if (_Car == value)
{
return;
}
_Car = value;
NotifyPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Windows;
namespace TreeViewTest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
MainWindowViewModel _MainWindowContext = new MainWindowViewModel();
public MainWindow()
{
DataContext = _MainWindowContext;
List<String> basicFeatures = new List<string>() { "Air Conditioning", "AM/FM Radio"};
Car Rav4 = new Car() { Make = "Toyota", Model = "Rav4", Year = 2001, Features = basicFeatures};
Car ModelX = new Car() { Make = "Tesla", Model = "Model X", Year = 2020, Features = basicFeatures};
List<Car> theseCars = new List<Car>() { Rav4, ModelX };
_MainWindowContext.Car = Rav4;
_MainWindowContext.Cars = theseCars;
InitializeComponent();
}
}
}
MainWindow.xaml
<Window x:Class="TreeViewTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TreeViewTest"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Grid.Column="0">
<TreeView Grid.Row="0" Grid.Column="0" Height="150">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding CarCollection}" DataType="{x:Type local:Cars}">
<StackPanel Orientation="Horizontal">
<TreeViewItem Header="{Binding Make}"/>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</StackPanel>
</Grid>
</Window>
添加
ItemsSource="{Binding Cars}"
到 TreeView
编辑
这就是将具有各自特征的汽车作为子节点进行布局的方式。
<TreeView Grid.Row="0" Grid.Column="0" Height="150" ItemsSource="{Binding Cars}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:Car}" ItemsSource="{Binding Features}">
<TextBlock Text="{Binding Make}"/>
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
您将 Cars 传递给 TreeView 控件本身,因此它有一个项目源。
<TreeView ItemsSource="{Binding Cars}">
然后你通过资源定义模板。在您的情况下,它是 HierarchicalDataTemplate,因为 cars 有另一个级别。
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:Car}" ItemsSource="{Binding Features}">
</HierarchicalDataTemplate>
</TreeView.Resources>
重要的是要说明您的 HierarchicalDataTemplate 数据类型是 Car,然后您还必须定义 ItemsSource。
基本上你对 WPF 说的是:每当你遇到一种汽车时,请布置一个层次结构并使用你可以在汽车类型上找到的功能集合。
在此之后您定义实际内容。内容是一个显示 Make 属性 from type Car 的 TextBlock,然后我们定义了 HierarchicalDataTemplate ItemTemplate。所以在这里我们要对 WPF 说,一旦您布置了 Car,请确保您也布置了子节点。在您的案例中没有特定的 属性 绑定,因为它是一个字符串列表。
<TextBlock Text="{Binding Make}"/>
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
我一直在自学 C#,一直想编写一个使用树视图的 WPF 应用程序。不过,我花了很多时间弄清楚如何让数据绑定与它一起工作。
有人可以告诉我哪里出错了吗?在这一点上,我只是想得到一些东西,任何东西都可以在树中显示。我发现的显示如何使用 treeview 的资源让我很困惑。
提前感谢您的宝贵时间
编辑: 感谢您的回复。将 ItemSource = {Cars} 添加到树视图中已经引入了我实例化的两辆车的 Make。我如何着手使汽车可以扩展以显示功能列表?我会尝试自己解决这个问题,但此时任何帮助都将不胜感激,因为我对这个问题感到有点沮丧。
Cars.cs
using System;
using System.Collections.Generic;
namespace TreeViewTest
{
public class Cars
{
public List<Car> CarCollection { get; set; }
}
public class Car
{
public String Make { get; set; }
public String Model { get; set; }
public int Year { get; set; }
public List<String> Features { get; set; }
}
}
MainWindowViewModel.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace TreeViewTest
{
public class MainWindowViewModel : INotifyPropertyChanged
{
private List<Car> _Cars;
public List<Car> Cars
{
get { return _Cars; }
set
{
if (_Cars == value)
{
return;
}
_Cars = value;
NotifyPropertyChanged();
}
}
public Car _Car;
public Car Car
{
get { return _Car; }
set
{
if (_Car == value)
{
return;
}
_Car = value;
NotifyPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Windows;
namespace TreeViewTest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
MainWindowViewModel _MainWindowContext = new MainWindowViewModel();
public MainWindow()
{
DataContext = _MainWindowContext;
List<String> basicFeatures = new List<string>() { "Air Conditioning", "AM/FM Radio"};
Car Rav4 = new Car() { Make = "Toyota", Model = "Rav4", Year = 2001, Features = basicFeatures};
Car ModelX = new Car() { Make = "Tesla", Model = "Model X", Year = 2020, Features = basicFeatures};
List<Car> theseCars = new List<Car>() { Rav4, ModelX };
_MainWindowContext.Car = Rav4;
_MainWindowContext.Cars = theseCars;
InitializeComponent();
}
}
}
MainWindow.xaml
<Window x:Class="TreeViewTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TreeViewTest"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Grid.Column="0">
<TreeView Grid.Row="0" Grid.Column="0" Height="150">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding CarCollection}" DataType="{x:Type local:Cars}">
<StackPanel Orientation="Horizontal">
<TreeViewItem Header="{Binding Make}"/>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</StackPanel>
</Grid>
</Window>
添加
ItemsSource="{Binding Cars}"
到 TreeView
编辑
这就是将具有各自特征的汽车作为子节点进行布局的方式。
<TreeView Grid.Row="0" Grid.Column="0" Height="150" ItemsSource="{Binding Cars}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:Car}" ItemsSource="{Binding Features}">
<TextBlock Text="{Binding Make}"/>
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
您将 Cars 传递给 TreeView 控件本身,因此它有一个项目源。
<TreeView ItemsSource="{Binding Cars}">
然后你通过资源定义模板。在您的情况下,它是 HierarchicalDataTemplate,因为 cars 有另一个级别。
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:Car}" ItemsSource="{Binding Features}">
</HierarchicalDataTemplate>
</TreeView.Resources>
重要的是要说明您的 HierarchicalDataTemplate 数据类型是 Car,然后您还必须定义 ItemsSource。 基本上你对 WPF 说的是:每当你遇到一种汽车时,请布置一个层次结构并使用你可以在汽车类型上找到的功能集合。
在此之后您定义实际内容。内容是一个显示 Make 属性 from type Car 的 TextBlock,然后我们定义了 HierarchicalDataTemplate ItemTemplate。所以在这里我们要对 WPF 说,一旦您布置了 Car,请确保您也布置了子节点。在您的案例中没有特定的 属性 绑定,因为它是一个字符串列表。
<TextBlock Text="{Binding Make}"/>
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>