WPF重要概念

一。逻辑树、可视树

逻辑树:在WPF中,用户界面里有一个对象树构建而成--逻辑树

          程序里使用的呈现在界面上的对象。

可视树:有逻辑树扩展而来。

        LogicalTreeHelper.GetChildren(obj as Dependencyobject)

       LogicalTreeHelper.FindLogicalNode(obj as Dependencyobject, string name)

        VisualTreeHelper.GetChild(obj, i)

二。依赖属性

     1。应用:属性触发器、依赖属性

     2。实现:与一般属性使用步骤一致,定义一个变量,定义属性

代码
         static MyButton()
         {

              //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 MinWidth="75" Name="lizhi1" Grid.Row="1" Content="触发器测试">
                   
<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>取得一个值之后:

  

代码
       FrameworkPropertyMetadata -->CoerceValueCallback;  //可以强制改变传递的值。
        DependencyProperty Register-->ValidateValueCallback;  //决定是否可以接受改变。
        FrameworkPropertyMetadata -->PropertyChangedCallback;  //值改变之后的事件。

   6.2 清楚依赖属性值:实例引用.ClearValue(依赖属性拥有类名.ForegroundProperty)

   6.3. DependencyPropertyHelp.GetValuesource    

7.附加属性

   7.1  应用:Grid.Row

                 StackPanel的字体设置。

        

   7.2 附加属性:把其他对象上的依赖属性,添加到本对象上,就像本对象也有这个属性一样

   7.3 实现:最终调用依赖属性上的属性值,依赖属性值具有继承关系。

隐藏行号 复制代码 这是一段程序代码。
  1. TextElement.FontSizeProperty = DependencyProperty.RegisterAttached(
    
  2. "FontSize", 
    
  3. typeof(double),
    
  4. typeof(TextElement),
    
  5. new FrameworkPropertyMetadata(
    
  6.     SystemFonts.MessageFontSize,
    
  7.     FrameworkPropertyMetadataOptions.Inherits | 
    
  8.     FrameworkPropertyMetadataOptions.AffectsRender |
    
  9.     FrameworkPropertyMetadataOptions.AffectsMeasure),
    
  10. new ValidateValueCallback(xxxx)
    
  11.     )
    
  12. )
    

    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;
                });

原文地址:https://www.cnblogs.com/SouthAurora/p/1750269.html