我正在努力学习和理解XAML中的WPF TreeView和数据绑定。我似乎无法掌握数据绑定的概念,非常感谢您的帮助。
ISSUE 在TreeView中不显示任何内容。我最感兴趣的是了解如何将WPF中的数据正确绑定到对象以实现树视图。
概念:考虑具有一组主题的SubjectList。为了这个例子,每个主题只有一个学生
TreeView中的预期输出
Maths
Student 1
Science
Student 2
Arts
Student 3
我当前的XAML尝试基于此处阅读的教程http://blogs.microsoft.co.il/pavely/2014/07/12/data-binding-for-a-wpf-treeview/。
在此之后,我有以下XAML:
<Window x:Class="WpfApplication1.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:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<TreeView x:Name="treeView" HorizontalAlignment="Left"
Height="284"
Margin="18,10,0,0"
VerticalAlignment="Top"
Width="115"
ItemsSource="{Binding SubjectList}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding SubjectList}"
DataType="{x:Type local:Subject}">
<TreeViewItem Header="{Binding SubjectName}"/>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</StackPanel>
MainWindow函数将Student对象添加到StudentList中:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Student s1 = new Student("Alex", 1);
Student s2 = new Student("Kevin", 2);
Student s3 = new Student("Sina", 3);
Student s4 = new Student("Evan", 4);
Subject a1 = new Subject("Maths", 1);
Subject a2 = new Subject("Science", 2);
Subject a3 = new Subject("Arts", 3);
a1.setStudent(s1);
a2.setStudent(s2);
a3.setStudent(s3);
Subjects list = new Subjects();
list.AddSubjects(a1);
list.AddSubjects(a2);
list.AddSubjects(a3);
DataContext = list;
}
}
类
class Subjects
{
private List<Subject> subjectList;
public List<Subject> SubjectList { get; set;}
public Subjects()
{
SubjectList = new List<Subject>();
}
public void AddSubjects(Subject s)
{
SubjectList.Add(s);
}
}
class Subject
{
private String subjectName;
private List<Student> studentList;
//accessor methods
public String SubjectName { get; set; }
public List<Student> StudentList { get; }
public Subject()
{
}
public Subject(string name, int id)
{
SubjectName = name;
StudentList = new List<Student>();
}
public void setStudent(Student aStudent)
{
StudentList.Add(aStudent);
}
}
class Student
{
public Student()
{
}
public Student(string name, int id)
{
StudentName = name;
StudentID = id;
}
private String studentName;
private int studentID;
//accessor methods
public String StudentName { get; set;}
public int StudentID { get; set; }
}
}
我做错了什么?任何能指出我正确方向的人都能更好地理解WPF中数据绑定的概念到一个对象列表,这将是我自学的一个巨大帮助!
更新1 :设置DataContext = list;并删除XAML中的DataContext引用解决了定义两个View的问题。
问题2::我仍然对View感到困惑。我添加了一个List作为Subject Class的属性。
如何从XAML中主题对象内的Student对象列表中检索学生名称?对于希望在TreeView中显示的任何/每个集合,您是否需要View?我希望了解这些作品如何协同工作。任何进一步的材料或协助非常感谢。
答案 0 :(得分:1)
您正在创建Subjects
视图模型的两个实例,一个在XAML中
<Window.DataContext>
<local:Subjects/>
</Window.DataContext>
和代码中的一个
Subjects list = new Subjects();
在后面的代码中向list
实例添加项目不会将它们添加到DataContext中的实例。
更改您的代码:
var list = (Subjects)DataContext;
list.AddSubjects(a1);
...
或者从XAML中删除DataContext赋值并将代码写在后面:
var list = new Subjects();
list.AddSubjects(a1);
...
DataContext = list;
也就是说,使用ObservableCollection
代替List
来通知收集更改可能是有意义的,例如在添加或删除主题时。
答案 1 :(得分:0)
所以我相信你的困惑植根于绑定的概念,所以我会试着为你澄清一下。
使用您发布的代码:
<Window x:Class="WpfApplication1.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:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<TreeView x:Name="treeView" HorizontalAlignment="Left"
Height="284"
Margin="18,10,0,0"
VerticalAlignment="Top"
Width="115"
ItemsSource="{Binding SubjectList}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding SubjectList}"
DataType="{x:Type local:Subject}">
<TreeViewItem Header="{Binding SubjectName}"/>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</StackPanel>
在您的代码中,您将datacontext设置为Subjects实例。这意味着窗口的datacontext是Subjects。
现在,当你深入到xaml时,你会到达stackpanel。这会继承相同的datacontext,因此stackpanel的datacontext仍然是Subjects。
现在进入树视图。 treeview的datacontext仍然是Subjects,这就是为什么你能够将ItemsSource属性绑定到SubjectList类上的属性SubjectList的原因。
现在,当你到达TreeView.ItemTemplate时,datacontext是来自SubjectList的单个项目,也就是Subject的实例。
HierachicalDataTemplate仍然使用Subject实例的相同上下文。您不能将HierarchicalDataTemplate的ItemsSource绑定到SubjectList,因为Subject类没有该属性。
您可以绑定到StudentList,因为Subject类确实具有该属性。
如果您要将ItemsSource绑定到StudentList,那么您可以在HierarchicalDataTemplate内部放置一个TextBox,其绑定到主题名称,因为HierachicalDataTemplate内部具有单个StudentItem的DataContext
所以最后工作代码看起来像这样:
<Window x:Class="WpfApplication1.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:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<TreeView x:Name="treeView" HorizontalAlignment="Left"
Height="284"
Margin="18,10,0,0"
VerticalAlignment="Top"
Width="115"
ItemsSource="{Binding SubjectList}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding StudentList}">
<TextBox Text="{Binding StudentName}"/>
<TextBox Text=" "/>
<TextBox Text="{Binding ID}"/>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</StackPanel>
所以总的来说你非常接近,但是我希望这可以帮助你理解当你深入研究绑定时会发生什么。如果你对任何事情感到困惑,请发表评论,我会尽量让它更清楚