ItemsControl的两种数据绑定方式
最近在学习ItemsControl这个控件的时候,查看了MSDN上面的一个例子,并且自己做了一些修改,这里主要使用了两种方式来进行相应的数据绑定,一种是使用DataContext,另外一种是直接将一个类绑定到前台,其实这两种方式原理差不多都是将数据模型的对象添加到一个ObservableCollection集合中,然后再绑定到前台,下面分别介绍两种绑定方式:
第一种是将数据存储在一个ObservableCollection集合中,然后作为ItemsControl的DataContext对象,下面分别贴出相关的代码:
<Window x:Class="TestGrid.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:TestGrid" Title="MainWindow" Height="350" Width="525"> <Grid> <ItemsControl Margin="10" x:Name="myItemsControl" ItemsSource="{Binding}"> <ItemsControl.Template> <ControlTemplate TargetType="ItemsControl"> <Border BorderBrush="Aqua" BorderThickness="1" CornerRadius="15"> <ItemsPresenter/> </Border> </ControlTemplate> </ItemsControl.Template> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <WrapPanel/> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> <ItemsControl.ItemTemplate> <DataTemplate DataType="{ x:Type local:DataSource}"> <DataTemplate.Resources> <Style TargetType="TextBlock"> <Setter Property="FontSize" Value="18"/> <Setter Property="HorizontalAlignment" Value="Center"/> </Style> </DataTemplate.Resources> <Grid> <Rectangle Fill="Green"/> <Ellipse Fill="Red"/> <StackPanel> <TextBlock Margin="3,3,3,0" Text="{Binding Path=Priority,Mode=TwoWay}"/> <TextBlock Margin="3,0,3,7" Text="{Binding Path=TaskName,Mode=TwoWay}"/> </StackPanel> </Grid> </DataTemplate> </ItemsControl.ItemTemplate> <ItemsControl.ItemContainerStyle> <Style> <Setter Property="Control.Width" Value="100"/> <Setter Property="Control.Margin" Value="5"/> <Style.Triggers> <Trigger Property="Control.IsMouseOver" Value="True"> <Setter Property="Control.ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=Content.Description}"/> </Trigger> </Style.Triggers> </Style> </ItemsControl.ItemContainerStyle> </ItemsControl> </Grid> </Window>
这里需要注意的地方是 ItemsSource="{Binding}"这句必须添加,否则后台的数据是无法添加到前台的,这个需要注意,这里贴出后台的代码
using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace TestGrid { /// <summary> /// MainWindow.xaml 的交互逻辑 /// </summary> public partial class MainWindow : Window { private ObservableCollection<DataSource> item = null; public MainWindow() { InitializeComponent(); item = new ObservableCollection<DataSource>(); item.Add( new DataSource() { Priority = "1", TaskName = "hello" } ); item.Add( new DataSource() { Priority = "2", TaskName = "whats" } ); item.Add( new DataSource() { Priority = "3", TaskName = "your" } ); item.Add( new DataSource() { Priority = "4", TaskName = "name" } ); item.Add( new DataSource() { Priority = "5", TaskName = "can" } ); item.Add( new DataSource() { Priority = "6", TaskName = "you" } ); this.myItemsControl.DataContext = item; } } }
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Linq; using System.Text; using System.Threading.Tasks; namespace TestGrid { public class DataSource : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; public DataSource() { } private string priority; public string Priority { get { return priority; } set { priority = value; OnPropertyChanged("Priority"); } } private string taskname; public string TaskName { get { return taskname; } set { taskname = value; OnPropertyChanged("TaskName"); } } protected void OnPropertyChanged(string propName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propName)); } } private List<DataSource> datasources; public List<DataSource> DataSources { get { return datasources; } set { datasources = value; } } } }
这里最重要的一句就是 this.myItemsControl.DataContext = item;这个是将刚才的集合绑定到ItemsControl控件上,这里需要我们的注意。
另外一种方式的数据绑定就是将一个类绑定到这个ItemsControl控件上,具体的方式如下:
<Window x:Class="TestGrid.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:TestGrid" Title="MainWindow" Height="350" Width="525"> <Window.Resources> <local:MyData x:Key="myDataSource"/> </Window.Resources> <Grid> <ItemsControl Margin="10" x:Name="myItemsControl" ItemsSource="{Binding Source={StaticResource myDataSource}}"> <ItemsControl.Template> <ControlTemplate TargetType="ItemsControl"> <Border BorderBrush="Aqua" BorderThickness="1" CornerRadius="15"> <ItemsPresenter/> </Border> </ControlTemplate> </ItemsControl.Template> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <WrapPanel/> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> <ItemsControl.ItemTemplate> <DataTemplate DataType="{ x:Type local:DataSource}"> <DataTemplate.Resources> <Style TargetType="TextBlock"> <Setter Property="FontSize" Value="18"/> <Setter Property="HorizontalAlignment" Value="Center"/> </Style> </DataTemplate.Resources> <Grid> <Rectangle Fill="Green"/> <Ellipse Fill="Red"/> <StackPanel> <TextBlock Margin="3,3,3,0" Text="{Binding Path=Priority,Mode=TwoWay}"/> <TextBlock Margin="3,0,3,7" Text="{Binding Path=TaskName,Mode=TwoWay}"/> </StackPanel> </Grid> </DataTemplate> </ItemsControl.ItemTemplate> <ItemsControl.ItemContainerStyle> <Style> <Setter Property="Control.Width" Value="100"/> <Setter Property="Control.Margin" Value="5"/> <Style.Triggers> <Trigger Property="Control.IsMouseOver" Value="True"> <Setter Property="Control.ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=Content.Description}"/> </Trigger> </Style.Triggers> </Style> </ItemsControl.ItemContainerStyle> </ItemsControl> </Grid> </Window>
这里我们通过资源来引用一个类,让后使用 ItemsSource="{Binding Source={StaticResource myDataSource}}"将这个类绑定到ItemsSource控件上面,这里贴出相关的代码,我们定义了一个MyData的类,将该类作为数据源绑定到前台上,这个类的代码如下
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Text; using System.Threading.Tasks; namespace TestGrid { public class MyData:ObservableCollection<DataSource> { public MyData() { Add (new DataSource() { Priority = "1", TaskName = "My" } ); Add(new DataSource() { Priority = "2", TaskName = "Name" } ); Add(new DataSource() { Priority = "3", TaskName = "Is" } ); Add(new DataSource() { Priority = "4", TaskName = "Ye" } ); Add(new DataSource() { Priority = "5", TaskName = "Bo" } ); } } }
这里面很重要的一部就是让这个类继承自 ObservableCollection<DataSource>,然后来添加相应的数据源,我们在使用继承的时候需要注意这些技巧。
其实这两种情况都是将一个数据集合绑定到前台,只不过是一些绑定的方式有所不同,实际的原理都是一样的!