WPF 中 数据绑定 ItemSource和 DataContext的不同点:
(1)DataContext 一般是一个非集合性质的对象,而ItemSource 更期望数据源是 集合对象。
(2)DataContext 是 FrameworkElement 类中定义的一个依赖属性(Dependency property),ItemsSource是 在ItemsControl 类中定义的。所有继承自FrameworkElement 的类(控件)都可以使用DataContext属性并给其赋值,但我们只能给ItemsSource赋值为集合对象
(3)DataContext不能产生模板,它只能用来筛选出数据,供其它控件来绑定。而ItemsSource主要作用就是给模板提供数据。
(4)DataContext主要用来抓取一些子元素需要使用的数据,以保证子元素能够顺利的使用数据。ItemsSource不会用来分享数据,它只是对定义好的元素有效。
以上可参照博客:
https://www.cnblogs.com/flytigger/p/4113121.html
下面来看下Itemsource,这里没有用到DataConetext,下面这个例子说明了(1)中的ItemSource 更期望数据源是 集合对象:
后台代码:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
List<string> listStrings = new List<string>();
for (int i = 0; i < 50; i++)
{
listStrings.Add(i.ToString());
}
listBox.ItemsSource = listStrings;
}
}
前台代码:
<Window x:Class="WpfApplication5.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:WpfApplication5"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ListBox Name="listBox"></ListBox>
</Grid>
</Window>
下面再来看看Datacontext和itemsource一起用的情况,从下面可以看出(2)中说明的情况,从调试中的代码可以看得更清楚一些,DataContext 一般是一个非集合性质的对象,然后前台的listbox绑定的是Datacontext中的MyListString的对象:
后台代码:
public partial class MainWindow : Window
{
public List<string> MyListString { get; set; }
public MainWindow()
{
InitializeComponent();
List<string> listStrings = new List<string>();
for (int i = 0; i < 50; i++)
{
listStrings.Add(i.ToString());
}
MyListString = listStrings;
DataContext = this;
}
}
前台代码:
<Window x:Class="WpfApplication5.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:WpfApplication5"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ListBox Name="listBox" ItemsSource="{Binding Path=MyListString}"></ListBox>
</Grid>
</Window>
接着来看一个常用的绑定模式,DataContext直接绑定到类,itemsource直接绑定到类的字段:
首先来一个MainViewModel的类,并给予一个Student的字段,给字段赋值。
public class MainViewModel
{
public List<Student> listStudent { get; set; }
public MainViewModel()
{
listStudent = new List<Student> { new Student("小王", 001), new Student("小张", 002), new Student("小李", 002) };
}
}
public class Student
{
public string Name { get; set; }
public int Id { get; set; }
public Student(string name, int id)
{
Name = name;
Id = id;
}
}
然后直接在前台用resourc绑定这个类,listbox的itemsource绑定这个类的字段Student。
前台绑定这个类的时候,实际上就相当于把这个类实例化了,listbox的itemsource只需要静态跟踪这个类的字段。
<Window x:Class="WpfApplication5.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:WpfApplication5"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:MainViewModel x:Key="mvm"/>
</Window.Resources>
<Grid>
<ListBox Name="listBox" ItemsSource="{Binding Source={StaticResource mvm},Path=listStudent}" DisplayMemberPath="Name"></ListBox>
</Grid>
</Window>
以上也可以换到后台表示:
换掉之后,前后台代码(这里需要在后台实例化):
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
MainViewModel mvm = new MainViewModel();
listBox.ItemsSource = mvm.listStudent;
}
}
<Window x:Class="WpfApplication5.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:WpfApplication5"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ListBox Name="listBox" DisplayMemberPath="Name"></ListBox>
</Grid>
</Window>
也可以稍微换一下绑定方式,不用Window.Resources,而改用Window.DataContext也可以:
<Window x:Class="WpfApplication5.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:WpfApplication5"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
<Grid>
<ListBox Name="listBox" ItemsSource="{Binding Path=listStudent}" DisplayMemberPath="Name"></ListBox>
</Grid>
</Window>
其实,我更喜欢最后一个绑定方式,然而我并不知道这个绑定方式和Window.Resources绑定方式究竟有什么内在的区别。