一。逻辑树、可视树
逻辑树:在WPF中,用户界面里有一个对象树构建而成--逻辑树
程序里使用的呈现在界面上的对象。
可视树:有逻辑树扩展而来。
LogicalTreeHelper.GetChildren(obj as Dependencyobject)
LogicalTreeHelper.FindLogicalNode(obj as Dependencyobject, string name)
VisualTreeHelper.GetChild(obj, i)
二。依赖属性
1。应用:属性触发器、依赖属性
2。实现:与一般属性使用步骤一致,定义一个变量,定义属性
{
//1.定义变量:都必须是Public,Static,并且有一个Property作为后缀
public static readonly DependencyProperty IsDefaultProperty;
/*
//2.创建属性
typeof(bool) //2.1 依赖属性类型
typeof(MyButton)//2.2 拥有这个属性的类
new FrameworkPropertyMetadata(false //2.3 FrameworkPropertyMetadata:可选,界面刷新...
new PropertyChangedCallback(OnIsDefaultChange // 最重要的一个属性PropertyChangedCallback:属性值改变时触发的事件。
*/
MyButton.IsDefaultProperty = DependencyProperty.Register("IsDefault",
typeof(bool), //2.1 依赖属性类型
typeof(MyButton), //2.2 拥有这个属性的类
new FrameworkPropertyMetadata(false, //2.3 FrameworkPropertyMetadata:可选,界面刷新...
new PropertyChangedCallback(OnIsDefaultChanged) // 最重要的一个属性PropertyChangedCallback:
) // 属性值改变时触发的事件。
);
}
public bool IsDefault //3.使用普通属性包装,原则上这里不能添加任何事件,只能是简单的包装。
{ //
get { return (bool)GetValue(MyButton.IsDefaultProperty); }
set { SetValue(MyButton.IsDefaultProperty, value); }
}
private static void OnIsDefaultChanged(
DependencyObject o, DependencyPropertyChangedEventArgs e)
{
//donginng.....
}
}
3.变更通知应用,参考属性触发器(WPF):
<Button.Style>
<Style TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="Blue"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
4。属性值继承:属性值沿着元素树的传递。
决定作用是否继承:FrameworkPropertyMetadata.Inherits
5. 依赖属性取值优先级别。
本地值
样式触发器
模版触发器
样式设置程序
主题样式触发器
主题样式设置程序
属性值继承.
默认值。
6。依赖属性的事件流程
6.1经过<5>取得一个值之后:
DependencyProperty Register-->ValidateValueCallback; //决定是否可以接受改变。
FrameworkPropertyMetadata -->PropertyChangedCallback; //值改变之后的事件。
6.2 清楚依赖属性值:实例引用.ClearValue(依赖属性拥有类名.ForegroundProperty)
6.3. DependencyPropertyHelp.GetValuesource
7.附加属性
7.1 应用:Grid.Row
StackPanel的字体设置。
7.2 附加属性:把其他对象上的依赖属性,添加到本对象上,就像本对象也有这个属性一样
7.3 实现:最终调用依赖属性上的属性值,依赖属性值具有继承关系。
TextElement.FontSizeProperty = DependencyProperty.RegisterAttached(
"FontSize",
typeof(double),
typeof(TextElement),
new FrameworkPropertyMetadata(
SystemFonts.MessageFontSize,
FrameworkPropertyMetadataOptions.Inherits |
FrameworkPropertyMetadataOptions.AffectsRender |
FrameworkPropertyMetadataOptions.AffectsMeasure),
new ValidateValueCallback(xxxx)
)
)
8 共享属性。FontSize,
Contral.FontSizeProperty = TextElement.FontSizeProperty.AddOwner(
type(Control),
new FrameworkPropertyMetadata(
SystemFonts.MessageFontSize,
FrameworkPropertyMetadataOptions.Inherits ))
三。路由事件。
1。路由
1。1必要性
1。2 路由类型
Tunneling(管道传递,向下)
Bubbling(冒泡,向上)
Direct(直接)不路由,但是可以用于事件触发器。
2。实现:
2。1
1: public class MyButton : ButtonBase
2: {
3: public static readonly RoutedEvent ClickEvent; //1.定¨义?:opublic static
4:
5: static MyButton()
6: {
7: //2.生ú成é
8: MyButton.ClickEvent = EventManager.RegisterRoutedEvent(
9: "Click",
10: RoutingStrategy.Bubble,
11: typeof(RoutedEventHandler),
12: typeof(MyButton)
13: );
14: }
15: //3。£三y包ü装°可é选?。£
16: public event RoutedEventHandler Click
17: {
18: add { AddHandler(MyButton.ClickEvent, value); }
19: remove { RemoveHandler(MyButton.ClickEvent, value); }
20: }
21:
22: //4。£触¥发¢
23: protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
24: {
25: //Base.Do....
26: RaiseEvent(new RoutedEventArgs(MyButton.ClickEvent, this))
27: }
28:
29: }
30:
2。2参数介绍RoutedEventArgs
Source-一开始出发该事件的元素(逻辑树的第一个元素)
OriginalSource --开始出发该事件的元素(可视树的第一个元素)
Handled--True:表示事件已经处理,不需要在路由,不管是管道还是冒泡
RoutedEvent --由那个事件触发
3。附加事件。
1。定义,每一个路由事件都可以当作附加事件使用。
存在必要性
2。实现。
1: <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
2: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
3: x:Class="AboutDialog" ListBox.SelectionChanged="ListBox_SelectionChanged"
4: Button.Click="Button_Click"
5: Title="About WPF Unleashed" SizeToContent="WidthAndHeight"
6: Background="OrangeRed">
7: <StackPanel>
8: <Label FontWeight="Bold" FontSize="20" Foreground="White">
9: WPF Unleashed (Version 3.0)
10: </Label>
11: <Label>© 2006 SAMS Publishing</Label>
12: <Label>Installed Chapters:</Label>
13: <ListBox>
14: <ListBoxItem>Chapter 1</ListBoxItem>
15: <ListBoxItem>Chapter 2</ListBoxItem>
16: </ListBox>
17: <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
18: <Button MinWidth="75" Margin="10">Help</Button>
19: <Button MinWidth="75" Margin="10">OK</Button>
20: </StackPanel>
21: <StatusBar>You have successfully registered this product.</StatusBar>
22: </StackPanel>
23: </Window>
24:
四、如何跟踪控件一个属性值的变化
DependencyPropertyDescriptor.FromProperty(控件类型.要跟踪的某个属性, typeof(控件类型))
.AddValueChanged(要跟踪的控件实例, (o, e) =>
{
var i = 1;
});
例如,要跟踪一个TextBox对象的IsReadOnly属性值改变,这个对象的实例是textbox:
DependencyPropertyDescriptor.FromProperty(TextBox.IsReadOnlyProperty, typeof(TextBox))
.AddValueChanged(textbox, (o, e) =>
{
var i = 1;
});