属性 依赖属性 依赖属性就是一种自己可以没有值,并能通过Binding从数据源获取值的属性。拥有依赖属性的对象被称为依赖对象。
传统开发中,一个对象占用的内存空间在使用new进行实例化的时候已经确定了,而WPF允许对象在创建的时候不包含用于存储数据的空间,而是拥有在需要用到数据的时候能够获取默认值、借用其他对象数据或实时分配空间的能力 。这种对象叫做依赖对象,这种获取数据的能力叫做依赖属性。
依赖对象要由DependencyObject
来实现,该类中具有GetValue和SetValue方法,这两个方法都是以DependencyProperty
对象为参数。
1 2 public object GetValue (DependencyProperty dp ) ;public void SetValue (DependencyProperty dp, object value ) ;
依赖属性的声明和使用 1 2 3 4 5 <StackPanel > <TextBox x:Name ="txt1" Margin ="5" /> <TextBox x:Name ="txt2" Margin ="5" /> <Button x:Name ="btn" Content ="OK" Margin ="5" Click ="Btn_Click" /> </StackPanel >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class Student : DependencyObject { public static readonly DependencyProperty NameProperty = DependencyProperty.Register("Name" , typeof (string ), typeof (Student)); } private void Btn_Click (object sender, RoutedEventArgs e ){ Student su = new Student(); su.SetValue(Student.NameProperty, this .txt1.Text); txt2.Text = (string )su.GetValue(Student.NameProperty); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 public class Student : DependencyObject { public static readonly DependencyProperty NameProperty = DependencyProperty.Register("Name" , typeof (string ), typeof (Student)); public string Name { get { return (string )GetValue(NameProperty); } set { SetValue(NameProperty, value ); } } public BindingExpressionBase SetBinding (DependencyProperty dp,BindingBase binding ) { return BindingOperations.SetBinding(this , dp, binding); } } private void Btn_Click (object sender, RoutedEventArgs e ){ Student su = new Student(); su.SetBinding(Student.NameProperty, new Binding("Text" ) { Source = txt1 }); txt2.SetBinding(TextBox.TextProperty, new Binding("Name" ) { Source = su }); }
尽管上面的Student类没有实现INotifyPropertyChanged接口,但是属性值发生改变时与之关联的Binding对象依然可以得到通知,依赖属性默认带有这样的功能。
可以使用propdp在vs中快速定义依赖属性代码段
附加属性 附加属性就是一个属性本来不属于某个对象,但是把这个对象放到特定环境后(宿主)会新增这个属性。
比如TextBox只有放在Grid里面,Grid.Column才会生效<TextBox Background="AliceBlue" Grid.Column="1" Grid.Row="1"/>
附加属性的声明和使用 附加属性的本质就是依赖属性,两者仅仅在包装器上有一些区别。
案例:人放在学校,才会有年级和班级,说明年级和班级是附加属性,宿主是学校。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class School : DependencyObject { public static int GetGrade (DependencyObject obj ) { return (int )obj.GetValue(GradeProperty); } public static void SetGrade (DependencyObject obj, int value ) { obj.SetValue(GradeProperty, value ); } public static readonly DependencyProperty GradeProperty = DependencyProperty.RegisterAttached("Grade" , typeof (int ), typeof (School), new PropertyMetadata(0 )); }
1 public class Human :DependencyObject {}
增加一个button按钮,然后添加点击事件
1 2 3 4 5 6 7 private void Button_Click (object sender, RoutedEventArgs e ){ Human human = new Human(); School.SetGrade(human, 6 ); int grade = School.GetGrade(human); MessageBox.Show(grade.ToString()); }
附加属性的本质就是依赖属性,所以附加属性也可以使用Binding依赖在其他对象上。
<TextBox Grid.Column="1" Grid.Row="1"/>
所对应的C#代码是
1 2 3 TextBox txt = new TextBox(); Grid.SetColumn(txt,1 ); Grid.setRow(txt,1 );
案例:
1 2 3 4 5 <Canvas > <Slider x:Name ="sldX" Width ="260" Minimum ="50" Maximum ="200" Canvas.Left ="15" Canvas.Top ="10" /> <Slider x:Name ="sldY" Width ="260" Minimum ="50" Maximum ="200" Canvas.Left ="15" Canvas.Top ="40" /> <Rectangle x:Name ="Rect" Fill ="Black" Width ="30" Height ="30" Canvas.Left ="{Binding ElementName=sldX,Path=Value}" Canvas.Top ="{Binding ElementName=sldY,Path=Value}" /> </Canvas >