附加属性说一个属性本来不属于某个对象,但由于某种需要而被后来附加上。也就是把对象放入一个特定环境后对象才具有的属性(表现出来就是被环境赋予的属性)就称为附加属性(Attached Property)。
附加属性的作用就是将属性与数据类型(宿主)解耦,让数据类型的设计更加灵活。附加属性的本质就是依赖属性(snippet: propa)。注册附加属性使用的是名为RegisterAttached的方法,且附加属性使用两个方法分别包装。
XAML:
<StackPanel Background="LightBlue">
<TextBox x:Name="textBox1" BorderBrush="Black" Margin="5"/>
<TextBox x:Name="textBox2" BorderBrush="Black" Margin="5, 0"/>
<Button Content="OK" Margin="5" Click="Button_Click"/>
</StackPanel>
C#代码:
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);
}
// Using a DependencyProperty as the backing store for MyProperty. This enables animation, styling, binding, etc...
public static readonly DependencyProperty GradeProperty =
DependencyProperty.RegisterAttached("Grade", typeof(int), typeof(School), new PropertyMetadata(0));
}
class Human : DependencyObject
{
}
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
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依赖在其他对象的数据上:
XAML:
<Canvas>
<Slider x:Name="sliderX" Canvas.Top="10" Canvas.Left="10" Width="260" Minimum="50" Maximum="200"/>
<Slider x:Name="sliderY" Canvas.Top="40" Canvas.Left="10" Width="260" Minimum="50" Maximum="200"/>
<Rectangle x:Name="rect" Fill="Blue" Width="30" Height="30" Canvas.Left="{Binding ElementName=sliderX, Path=Value}" Canvas.Top="{Binding ElementName=sliderY, Path=Value}"/>
</Canvas>
与之等效的C#代码:
this.rect.SetBinding(Canvas.LeftProperty, new Binding("Value"){ Source = sliderX });
this.rect.SetBinding(Canvas.TopProperty, new Binding("Value"){ Source = sliderY });
事件系统在WPF中进化为路由事件(Routed Event),并在其基础上衍生出命令传递机制。
路由(Route)大意:起点与终点有若干个中转站,从起点出发后经过每个中转站时要做出选择,最终以正确的路劲到达终点。
WPF中有两种"树":一种叫逻辑树(Logical Tree),一种叫可视元素树(Visual Tree)。Logical Tree最显著的特点就是它完全由布局组件和控件构成(包括列表类控件中的条目元素),换句话说就是它的每个结点不是布局组件就是控件。
如果想在Logical Tree上导航或查找元素,可以借助LogicalTreeHelper类的static方法来实现;如果想在Visual Tree上导航或查找元素,则可借助VisualTreeHelper类的static方法来实现。
事件模型的3个关键点:
事件的拥有者:消息的发送者。事件的宿主可以在某些条件下激发它所拥有的事件,即事件被触发。事件被触发则消息被发送。
事件的响应者:即消息的接收者、处理者。事件接收者使用其事件处理器(Event Handler)对事件做出响应。
事件的订阅关系:如果对象A关注对象B的某个事件是否发生,则称A订阅了B�A事件。事件实际上是一个使用event关键字修饰的委托(Delegate)类型成员变量,事件处理器则是一个函数,说A订阅了B的事件,本质上就是让B.Event与A.EventHandler关联起来。所谓事件激发就是B.Event被调用,这时,与其关联的A.EventHandler就会被调用,将这种事件模型称为直接事件模型或CLR事件模型。