按照现在网上关于DataContext的普遍说法,WPF的UI是树状的,每个节点都是控件,所以每个节点都有DataContext属性,如果一个Binding找不到自己的Source那他就会沿着这个UI树一直往上找,直到找到和Path对应的那个属性,如果到最外层也没找到,那就没有数据源。
可我发现好像并不像是这样,下面用一个例子来说明吧。
新建一个类,为Human.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WpfApplication20190917B
{
//人类
class Human
{
private string name;//姓名
public string Name
{
get { return name; }
set { name = value; }
}
private int age;//年龄
public int Age
{
get { return age; }
set { age = value; }
}
private double height;//身高(单位:cm)
public double Height
{
get { return height; }
set { height = value; }
}
private double weight;//体重(单位:斤)
public double Weight
{
get { return weight; }
set { weight = value; }
}
public Human() { }
public Human(string Name, int Age, double Height, double Weight)
{
this.name = Name;
this.age = Age;
this.height = Height;
this.weight = Weight;
}
}
}
再新建一个类叫Man.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WpfApplication20190917B
{
//男人
class Man : Human
{
private double jjLength;//丁丁长度(单位:cm)
public double JjLength
{
get { return jjLength; }
set { jjLength = value; }
}
public Man()
: base()
{
}
public Man(string Name, int Age, double Height, double Weight, double JjLength):base(Name,Age,Height,Weight)
{
this.jjLength = JjLength;
}
}
}
还得再新建一个类叫Woman.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WpfApplication20190917B
{
//女人
class Woman : Human
{
private string cup;//罩杯
public string Cup
{
get { return cup; }
set { cup = value; }
}
public Woman() : base() { }
public Woman(string Name, int Age, double Height, double Weight, string Cup)
: base(Name, Age, Height, Weight)
{
this.cup = Cup;
}
}
}
MainWindow.xaml代码如下
<Window x:Class="WpfApplication20190917B.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid Name="grid1">
<Grid Name="grid2">
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Text="姓名:"/>
<TextBlock Text="年龄:" Grid.Row="1"/>
<TextBlock Text="身高:" Grid.Row="2"/>
<TextBlock Text="体重:" Grid.Row="3"/>
<TextBlock Text="丁丁长度:" Grid.Row="4"/>
<TextBlock Text="罩杯:" Grid.Row="5"/>
<TextBlock Name="name" Text="{Binding Path=Name}" Grid.Column="1"/>
<TextBlock Name="age" Text="{Binding Path=Age}" Grid.Row="1" Grid.Column="1"/>
<TextBlock Name="height" Text="{Binding Path=Height}" Grid.Row="2" Grid.Column="1"/>
<TextBlock Name="weight" Text="{Binding Path=Weight}" Grid.Row="3" Grid.Column="1"/>
<TextBlock Name="jj_length" Text="{Binding Path=JjLength}" Grid.Row="4" Grid.Column="1"/>
<TextBlock Name="cup" Text="{Binding Path=Cup}" Grid.Row="5" Grid.Column="1"/>
</Grid>
</Grid>
</Window>
MainWindow.xaml.cs代码如下
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
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 WpfApplication20190917B
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Man man1 = new Man("亚当",25,160.1,130.5,18.3);
Woman woman1 = new Woman("夏娃",22,155.9,115.0,"B罩");
this.grid2.DataContext = man1;
this.grid1.DataContext = woman1;
}
}
}
运行结果
会发现罩杯没有值。
上面例子中,grid2绑定了亚当的数据,所以前5个属性是有值的。理论上来说cup这个控件的Binding在grid2.DataContext找不到Cup这一属性,应该会再次往上找啊,再往上是grid1,绑定的是夏娃的数据,应当能够获取值的,实际上并没有。
我猜测Binding去查找DataContext的值应该是这么查找的:只要控件往上找的过程中找到了DataContext不为空的控件就不会再往上找了,不管这个DataContext里面有没有我需要的属性。
为了进一步验证,我们在MainWindow.xaml.cs多加一行代码
Woman woman2 = new Woman("柳岩", 39, 162.0, 104.3, "G罩");
this.jj_length.DataContext = woman2;
也就是给jj_length这个控件设置了DataContext,运行效果如下
会发现丁丁长度也确实没有值了,也证明了我的猜想。
最后,把MainWindow.xaml.cs代码改成如下,来看一看效果
Man man1 = new Man("亚当",25,160.1,130.5,18.3);
Woman woman1 = new Woman("夏娃",22,155.9,115.0,"B罩");
this.grid2.DataContext = man1;
this.grid1.DataContext = woman1;
Woman woman2 = new Woman("柳岩", 39, 162.0, 104.3, "G罩");
this.cup.DataContext = woman2;