Binding(三)——使用DataContext作为Binding的源

前面的例子都是将CLR类型的对象指定为Binding的Source,使用了两种方法——把对象赋值个Binding.Source或把对象的Name赋值给Binding.ElementName。

DataContext属性被定义在FrameworkElement类中,这个类是WPF控件的基类,意味着所有WPF空间都具备这个属性。WPF的UI布局是树形结构,每个节点都是空间,由此可以推出另一个结论——UI元素树的每个结点都有DataContext。

这一点非常重要,因为当一个Binding只知道自己的Path而不知道自己的Source时,它会沿着UI元素树一路向树的根部找过去,每路过一个结点就要看看这个结点的DataContext是否具有Path所指定的属性。如果有,就把这个对象作为自己的Source;如果没有,那就继续找,如果到了树的根部还没有找到,那这个Binding就没有Source,因而也不会得到数据。看如下例子。

创建一个Student类,具有Id、Name、Age三个属性:

    public class Student
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
    }

然后在XAML创建程序的UI。

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication1"
        Title="Binding Source" Height="135" Width="300">
    <StackPanel Background="LightBlue">
        <StackPanel.DataContext>
            <local:Student Id="6" Name="Tim" Age="29"/>
        </StackPanel.DataContext>
        <Grid>
            <StackPanel>
                <TextBox Text="{Binding Path=Id}" Margin="5"/>
                <TextBox Text="{Binding Path=Name}" Margin="5"/>
                <TextBox Text="{Binding Path=Age}" Margin="5"/>
            </StackPanel>
        </Grid>
    </StackPanel>
</Window>

UI布局可用如下的UI树了表示:


这样,这3个TextBox的Binding就会自动向UI元素树的上层去寻找可用的DataContext对象。最终,他们在最外层的StackPanel身上找到了可用的DataContext对象。

这样,当某个DataContext是一个简单类型对象的时候,我们可以完全能看到一个“既没有Path有没有Source”的Binding。

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        Title="Binding Source" Height="135" Width="300">
    <StackPanel Background="LightBlue">
        <StackPanel.DataContext>
            <sys:String>Hello Tom!</sys:String>
        </StackPanel.DataContext>
        <TextBlock Text="{Binding .}" Margin="5"/>
        <Grid>
            <Grid.DataContext>
                <sys:String>Hello Jerry!</sys:String>
            </Grid.DataContext>
            <StackPanel>
                <TextBlock Text="{Binding .}" Margin="5"/>
            </StackPanel>
        </Grid>
    </StackPanel>
</Window>

运行效果如下:


你可能会想,Binding是怎样自动向UI元素树的上层寻找DataContext对并把它作为Source的呢?DataContext是一种依赖属性,依赖属性有一个很重要的特点就是当你没有为控件的某个依赖属性显示赋值时,控件会把自己容器的属性值“借过来”当作自己的属性值。因此,“Binding沿着UI元素树向上找”只是WPF给我们的一个错觉,实际上是属性沿着UI元素树向下传递了。

在实际工作中DataContext的用法是十分灵活的。比如:

  1. 当UI的多个控件都是用Binding关注同一个对象时,不妨采用DataContext。
  2. 当作为Source的对象不能被直接访问的时候——比如B窗体内的控件想把A窗体内的空间当做自己的Binding源时,但A窗体内的控件是private访问级别,这时候就可以把这个控件作为窗体A的DataContext(这个属性是public访问级别)从而暴露数据。
  3. DataContext本身是一个依赖属性,可以使用Binding把它关联到一个数据源上。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值