zoukankan      html  css  js  c++  java
  • WPF Unleashed Chapter 3:Important New Concepts in WPF Dependency Properties(Attached property)

    Attached Properties
      
            Attached property是DP的一种特殊形态。它可将任意对象进行附加译。第一次听到这个名字可能会感到奇怪,但是WPF中的很多应用都会用到attached property。   
      
            在About dialog的例子中,比起在窗体级设置FontSize和FontStyle属性,在StackPanel控件里进行设置更加合适。但直接将这两个属性设置到StackPanel上是无效的,因为StackPanel自身并没有字体相关属性。所以必须使用FontSize和FontStyle的attached property,TextElement类定义了这两个属性。List3.5演示如如何使用attached property,图3.6为List3.5中代码的运行结果   
      
    LISTING 3.5 The About Dialog with Font Properties Moved to the Inner StackPanel   
    <Window xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”   
          Title=”About WPF Unleashed” SizeToContent=”WidthAndHeight”   
          Background=”OrangeRed”>   
          <StackPanel>   
                <Label FontWeight=”Bold” FontSize=”20” Foreground=”White”>   
                      WPF Unleashed (Version 3.0)   
                </Label>   
                <Label>© 2006 SAMS Publishing</Label>   
                <Label>Installed Chapters:</Label>   
                <ListBox>   
                      <ListBoxItem>Chapter 1</ListBoxItem>   
                      <ListBoxItem>Chapter 2</ListBoxItem>   
                </ListBox>   
                <StackPanel TextElement.FontSize=”30” TextElement.FontStyle=”Italic”   
                      Orientation=”Horizontal” HorizontalAlignment=”Center”>   
                      <Button MinWidth=”75” Margin=”10”>Help</Button>   
                      <Button MinWidth=”75” Margin=”10”>OK</Button>   
                </StackPanel>   
                <StatusBar>You have successfully registered this product.</StatusBar>   
          </StackPanel>   
    </Window>   
      
      
            TextElement.FontSize 和TextElement.FontStyle 必须设置在StackPanel内部,因为StackPanel没有字体相关的属性。当XAML的解析器或编译器遇到这种语法时,会去调用TextElement(有时也叫做attachd property提供者)的静态方法SetFontSize和SetFontStyle。List3.5中XAML代码对应的等效c#代码为:    
      
          StackPanel panel = new StackPanel();   
          TextElement.SetFontSize(panel, 30);   
          TextElement.SetFontStyle(panel, FontStyles.Italic);   
          panel.Orientation = Orientation.Horizontal;   
          panel.HorizontalAlignment = HorizontalAlignment.Center;   
          Button helpButton = new Button();   
          helpButton.MinWidth = 75;   
          helpButton.Margin = new Thickness(10);   
          helpButton.Content = “Help”;   
          Button okButton = new Button();   
          okButton.MinWidth = 75;   
          okButton.Margin = new Thickness(10);   
          okButton.Content = “OK”;   
          panel.Children.Add(helpButton);   
          panel.Children.Add(okButton);    
             
            注意FontStyles.Italic, Orientation.Horizontal和HorizontalAlignment。Center 这些枚举类型在XAML中分别为Italic,Horizontal和Center。这些转换是由.NET Framework的EnumConverter的转换器完成的。    
      
            上面的c#代码显示了List3.5中的XAML完成的工作并不神奇。只是通过一个方法将元素和不相关的属性来联系到一起。 实际上,SetFontSize这类方法在内部都调用了相同的DependencyObject.SetValue方法:    
      
          public static void SetFontSize(DependencyObject element, double value)   
          {   
                element.SetValue(TextElement.FontSizeProperty, value);   
          }
     
            和SetValue方法类似,attached property也定义了GetXXX的静态方法(xxx是属性的名称),用来调用DependencyObject.GetValue方法:    
      
          public static double GetFontSize(DependencyObject element)   
          {   
                return (double)element.GetValue(TextElement.FontSizeProperty);   
          }    
      
        使用属性包装器时,一定不要在GetXXX和SetXXX方法里添加GetValue和SetValue以外的代码。
        
    DIGGING DEEPER
      
    Understanding the Attached Property Provider   
      
            List3.5中FontSize和FontStyle的attached property最令人困惑的就是这两个attached property既没有定义在Button上,也没有定义在那些含有FontSize和FontStyle的控件上。却是由看似毫不相关的TextElement类来定义的。TextElement.FontSizeProperty是独立于控件的FontSizeProperty之外的一个DP,那么attached proeprty是如何运转的呢?关键是attached property的注册方式。如果您查看了TextElement的源代码,会看到以下代码:    
      
          TextElement.FontSizeProperty = DependencyProperty.RegisterAttached(   
          “FontSize”, typeof(double), typeof(TextElement), new FrameworkPropertyMetadata(   
          SystemFonts.MessageFontSize, FrameworkPropertyMetadataOptions.Inherits |   
          FrameworkPropertyMetadataOptions.AffectsRender |   
          FrameworkPropertyMetadataOptions.AffectsMeasure),   
          new ValidateValueCallback(TextElement.IsValidFontSize));
      
     
          除了针对attach property的应用场景对元数据进行了优化之外,上面的代码里和之前为Button控件注册IsDefaultProperty是类似的。
             
            另一方面,WPF的控件本身并没有注册FontSize的DP。而是调TextElement类的AddOwner方法,获得了TextElement类的FontSize实例的副本:   
      
          Control.FontSizeProperty = TextElement.FontSizeProperty.AddOwner(   
          typeof(Control), new FrameworkPropertyMetadata(SystemFonts.MessageFontSize,   FrameworkPropertyMetadataOptions.Inherits));   
            
          所以,控件的FontSize,FontStyle,以及这些和字体相关的DP,都是来源与TextElement!   
         理解起来会有些混乱,幸运的是,在大多情况下,那些暴露attatched property(例如GetXXX和SetXXX方法)的类实际上就是那些使用DependencyProperty.RegisterAttached方法定义了DP的类。

      
            虽然About dialog例子中使用attached property是为了演示属性值继承,但实际上这个特性更多应用在用户界面元素的布局上。(实际上,attached property本身就是为了WPF的布局系统而设计的。)继承Panel类的各种布局类都定义了attached property,用于控制它们内部元素的摆放。这样,我们只需要在面板(panel)中定义各自的布局行为就可以了,而没必要将这些行为附加到他们的子元素上。attached property的另一个优点是,它增强了布局系统的扩展性:用户可以创建一个新型的Panel,并定义相应的attached property。第六章Layout with Panels和第十七章Layout with Custom Panels将详细介绍
      
     DIGGING DEEPER
      
    Attached Properties as an Extensibility Mechanism   
      
            和以前的Windows Forms技术一样,WPF内的许多类都定义了Tag属性(类型为System.Object)。该属性可以存储任意的对象的实例。而attached property也有Tag类似功能,它可以将用户数据与继承自DependencyObject的对象联系在一起,并且功能更强大,更灵活。
      
            在XAML中使用attached property要用到静态的方法SetXXX,但您可以使用程序代码来避开这个麻烦,只需要直接调用DependencyObject类的SetValue方法就可以了。这样您就可以将任意DP作为attached property使用了。例如,下面的代码中,使用了SetValue将ListBox控件的IsTextSearchEnabled属性“系”到Button控件上,并分配了值:   
        
    // Attach an unrelated property to a Button and set its value to true:   
    okButton.SetValue(ListBox.IsTextSearchEnabledProperty, true);
      
      
            虽然看上去没什么意义,并且也没能给Button带来任何新的功能,但是您通过这种方式就可以随意消费这个属性值,这对于应用程序或组件来说很有用处。
            我们可以使用这种方式对元素进行扩展。例如,FrameworkElement类的Tag是个DP,所以可以将它附加到GeometryModel3D对象(该类是sealed的,并且没有Tag属性。第十二章3D Graphics将介绍)上:   
      
    GeometryModel3D model = new GeometryModel3D();   
    model.SetValue(FrameworkElement.TagProperty, “my custom data”);
      
      
    这是WPF在不使用继承机制的情况对元素进行可扩展以一种方式。


                     下一章将介绍Routed Events
    如果您有WPF方面的问题,可以给我留言一起探讨,感谢大家浏览
  • 相关阅读:
    hadoop再次集群搭建(3)-如何选择相应的hadoop版本
    48. Rotate Image
    352. Data Stream as Disjoint Interval
    163. Missing Ranges
    228. Summary Ranges
    147. Insertion Sort List
    324. Wiggle Sort II
    215. Kth Largest Element in an Array
    快速排序
    280. Wiggle Sort
  • 原文地址:https://www.cnblogs.com/stswordman/p/804872.html
Copyright © 2011-2022 走看看