WPF的Binding学习笔记(三)
在笔记(一)中记了点Binding的Path相关, 因为Binding的带参构造器就只有Path的参数.
所以Path是很重要的, 有了Path, 即使在没有指定Source的时候, Binding也会随着UI元素树一层一层往外找DataContext对象, 判断是否具有相应的Path, 有就拿来用.
一, DataContext属性与Binding
笔记(一)中的Binding, 除了控件间的Binding, 其他都是在C#代码处完成的.
如何在XAML中Binding那些在C#中定义的实例呢?
方法之一就是使用DataContext.
1, 准备一个类
public class Student { public Student(string id, string name, int age) { this.Name = name; this.Id = id; this.Age = age; } public string Id { get; set; } public string Name { get; set; } public int Age { get; set; } }
2, 实例化, 然后赋值给窗体的DataContext
public partial class Window1 : Window { public Window1() { InitializeComponent(); Student stu = new Student("101", "巴尔扎克", 16); this.DataContext = stu ;
}
}
3, 准备XAML
<StackPanel> <TextBlock Text="{Binding Id}" Margin="5" /> <TextBlock Text="{Binding Name}" Margin="5" /> <TextBlock Text="{Binding Age}" Margin="5" /> </StackPanel>
运行, 出现如下界面
这样就成功了.
于是我朋友说, 那我直接把窗体自己做自己的DataContext, 然后定义的那些属性都能找到?
汗, 还真是能找到. 于是他说, 那如果我有多个数据源要分别Binding, 就多准备一些窗体的属性, 那XAML那边写起来就简单了.
汗, 效果的确是能实现, 其他的不谈...
下面来试一下
4, 添加window1的属性并修改实例化部分的代码
public partial class Window1 : Window { public Window1() { InitializeComponent(); stu = new Student("101", "巴尔扎克", 16);//这边实例化后赋值的对象是属性 this.DataContext = this;//这里改成this了 } public Student stu { get; set; } }
5, 修改XAML处的Binding
<StackPanel> <TextBlock Text="{Binding stu.Id}" Margin="5" /> <TextBlock Text="{Binding stu.Name}" Margin="5" /> <TextBlock Text="{Binding stu.Age}" Margin="5" /> </StackPanel>
F5运行, 成功
当然, 在上述示例中如果使用StackPanel的DataContext的话也行.
看到这里是否会觉得很奇怪, 好像跟路由事件的冒泡路由很像?
可惜, 冒泡路由是主动的, 而Binding才能这么牛, 只是作为依赖属性没显示指定DataContext的控件会自动使用其容器的DataContext而已.
测试开始!
还是上面的示例, XAML处给StackPanel指定一个Name="stackPanel", 然后把C#处指定DataContext部分的代码修改如下
public Window1() { InitializeComponent(); stu = new Student("101", "巴尔扎克", 16); this.DataContext = this; string strBuf = "Wahahaahaha"; stackPanel.DataContext = strBuf; }
F5运行, 发现空白一片...因为这些TextBlock使用的是上一级节点的DataContext, 而StackPanel的DataContext是个string类型, 没有Path想要的...残念了
突然想到一个很诡异的情况, 就是DataContext正好就是需要类型, 比如正好是string
那么就会出现
<TextBlock Text="{Binding}" Margin="5" />
这样诡异的Binding, 此后再遇也就不奇怪啦~