silverlight DataContext
1、DataContext 是在 FrameworkElement 里面的一个属性。
FrameworkElement 的关系可以看上一个日记。
2、简单来说,FrameworkElement 是所有可视化界面元素的基类,而DataContext 是它里面的一个属性。
我们的 绑定是基于使用这个 DataContext 去做绑定的,对于所有的界面都可以这么做。
3、DataContext 的特征,它会通知它的视觉树(VisualTree)下面的子节点。
来一个经典DEMO:
using System.Windows.Data; using System.Windows.Media; using System.Windows; using System; namespace Class4Samples { public class GetVisualParentConverter : IValueConverter { #region IValueConverter Members public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture) { DependencyObject parent = value as DependencyObject; while (true) { parent = VisualTreeHelper.GetParent(parent as DependencyObject); if (parent == null) break; if (parameter as string == parent.GetType().ToString()) { return parent; } } return null; } public object ConvertBack(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new System.NotImplementedException(); } #endregion } }
前台XAML: 这里有很多绑定技巧,需要理解清楚!
<UserControl 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:Class4Samples" xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data" x:Class="Class4Samples.DataContext" mc:Ignorable="d" x:Name="userControl" d:DesignWidth="640" d:DesignHeight="480"> <UserControl.Resources> <local:GetVisualParentConverter x:Key="GetVisualParentConverterDataSource" d:IsDataSource="True"/> <Style x:Key="ContentControlStyle" TargetType="ContentControl"> <Setter Property="Foreground" Value="#FF000000"/> <Setter Property="HorizontalContentAlignment" Value="Left"/> <Setter Property="VerticalContentAlignment" Value="Top"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="ContentControl"> <Border BorderBrush="#FFA9FFBF" BorderThickness="5" CornerRadius="10"> <ComboBox ItemsSource="{Binding}"/> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style> <DataTemplate x:Key="DataTemplate"> <Border BorderBrush="#FF1BB8FF" BorderThickness="1" CornerRadius="10"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition/> <RowDefinition/> <RowDefinition/> <RowDefinition/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> <TextBlock Foreground="#FF002EFF" Text="{Binding}" TextWrapping="Wrap" Height="20"/> <TextBlock Text="Parent: " TextWrapping="Wrap" Grid.Row="1"/> <TextBlock Grid.Column="1" Text="{Binding ., RelativeSource={RelativeSource TemplatedParent}}" TextWrapping="Wrap" d:LayoutOverrides="Width, Height" Grid.Row="1"/> <TextBlock Text="Parent.Parent: " TextWrapping="Wrap" Grid.Row="2"/> <TextBlock Grid.Column="1" Text="{Binding Parent, RelativeSource={RelativeSource TemplatedParent}}" TextWrapping="Wrap" d:LayoutOverrides="Width, Height" Grid.Row="2"/> <TextBlock Text="Parent.Parent.Parent: " TextWrapping="Wrap" Grid.Row="3"/> <TextBlock Grid.Column="1" Grid.Row="3" Text="{Binding Parent.Parent, RelativeSource={RelativeSource TemplatedParent}}" TextWrapping="Wrap" d:LayoutOverrides="Width, Height"/> <TextBlock Text="GetVisualParentConverter to Get ListBox: " TextWrapping="Wrap" Grid.Row="4"/> <TextBlock Grid.Column="1" Grid.Row="4" Text="{Binding Converter={StaticResource GetVisualParentConverterDataSource}, ConverterParameter=System.Windows.Controls.ListBox, Mode=OneWay}" DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}" TextWrapping="Wrap"/> </Grid> </Border> </DataTemplate> </UserControl.Resources> <Grid x:Name="LayoutRoot"> <Grid VerticalAlignment="Top" DataContext="{Binding Items, ElementName=userControl, Mode=OneWay}" HorizontalAlignment="Center" Width="400"> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition/> </Grid.RowDefinitions> <TextBlock VerticalAlignment="Top" Text="{Binding}" TextWrapping="Wrap"/> <ListBox VerticalAlignment="Top" Grid.Row="1" ItemsSource="{Binding}"/> <ComboBox VerticalAlignment="Top" Height="20" Grid.Column="1"> <ListBox ItemsSource="{Binding}"/> <data:DataGrid ItemsSource="{Binding}"/> </ComboBox> <ContentControl Grid.Row="1" Style="{StaticResource ContentControlStyle}" Grid.Column="1"/> </Grid> <ListBox ItemTemplate="{StaticResource DataTemplate}" ItemsSource="{Binding Items, ElementName=userControl, Mode=OneWay}" x:Name="list" Margin="120,136,120,120"/> </Grid> </UserControl>
后台CS代码:
using System; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Ink; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using System.Collections.ObjectModel; namespace Class4Samples { public partial class DataContext : UserControl { public DataContext() { // Required to initialize variables InitializeComponent(); this.PrepareDatas(); } private void PrepareDatas() { this.Items = new ObservableCollection<string>(); this.Items.Add("Lewis Wu"); this.Items.Add("Jerry Jiang"); this.Items.Add("Martin Du"); } public ObservableCollection<string> Items { get { return (ObservableCollection<string>)GetValue(ItemsProperty); } set { SetValue(ItemsProperty, value); } } public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register("Items", typeof(ObservableCollection<string>), typeof(DataContext), new PropertyMetadata(null)); } }