zoukankan      html  css  js  c++  java
  • WPF学习(四) - 附加属性

      冷静了一晚,我就当这次学习的过程是在看狗血剧情的武打小说吧:没有垃圾的武术,只有垃圾的武者……

      还有个话儿怎么说来着:你们是用户,不是客户,也就有个使用的权力。搞清楚身份,别叽叽歪歪的!

      没办法,全世界都说好的东西,我也得从善,继续学习。

      从用法的角度来看,附加属性与依赖属性有所不同。

      定义依赖属性,是为了满足绑定技术的要求,实现对象间的数据同步的目的。

      而附加属性,是为了实现其他对象具有我的某些属性这个目的。

      第一次看到附加属性的应用,是在XAML文档中出现的。

      <Window>
        <Grid>
          <Button x:Name = "btn1" Grid.Row = "1"/>
        </Grid>
      </Window>

      Button,本身没有布局关系的属性,外层的Grid了一些布局关系属性,Button只要引用过来,就可以给自己重新定位,多么神奇的实现!

      附加属性的意思是:我定义的特征可以让别人拿去修饰他自己。换个说法,别人拿了我的牲征,作为他的附加属性来描述自己。

      这里,把“我”定义个名称叫做宿主,“别人”叫做订购者,实现一个简单的附加属性的用例。

        class HostObject : DependencyObject
        {
    
            public static string GetAttachedText ( DependencyObject obj )
            {
                return ( string ) obj.GetValue ( AttachedTextProperty );
            }
    
            public static void SetAttachedText ( DependencyObject obj, string value )
            {
                obj.SetValue ( AttachedTextProperty, value );
            }
    
            // 我觉得这种属性应该叫签证,注册的过程就是登记
            public static readonly DependencyProperty AttachedTextProperty =
                DependencyProperty.RegisterAttached ( "AttachedText", typeof ( string ), typeof ( HostObject ));
    
        }
    定义宿主
        class Order : DependencyObject
        {
        }
    定义订购者
            public static void TestAttachedProperty ( )
            {
                //规规矩矩的用法,从宿主存取值
                Order a = new Order ( );
                HostObject.SetAttachedText ( a, "aaaa" );
                Console.WriteLine ( HostObject.GetAttachedText ( a ) );
    
                //再来一次,两个对象各自存取自己的值
                Order b = new Order ( );
                HostObject.SetAttachedText ( b, "bbbb" );
                Console.WriteLine ( HostObject.GetAttachedText ( b ) );
            }
    测试用例

      可以看到,宿主和订购者的类之间没有任何的关系。

      从表现形式上看,宿主提供GetAttachedText和SetAttachedText方法,允许订购者订购自己的专用寄存器,最终看起来订购者具备一些额外的属性。细看这两个方法的实现过程,其实是由订购者自己来调用GetValue和SetValue方法,达到存/取值的目的,而不是宿主来做这些事儿。

      通过前日的学习,我已知道,附加属性存储值的地方既不在宿主中,也不在订购者中,而是用另外的一个容器统一管理。

      使用附加属性的对象都要求从DependencyObject派生,这样就自带GetValue和SetValue方法,可以从容器里存取数据了。

      宿主给自己包上一层糖衣,实现GetAttachedText和SetAttachedText方法,表现成从宿主对象上,可以存取订购者的附加属性。

      我们也可以从订购者处,存取附加属性

            public static void TestAttachedProperty2 ( )
            {
                Order c = new Order ( );
                c.SetValue ( HostObject.AttachedTextProperty, "cccc" );
                string value = ( string ) c.GetValue ( HostObject.AttachedTextProperty );
                Console.WriteLine ( value );
            }
    从订购者存取值

      我可以更放纵一点

            public static void TestAttachedProperty3 ( )
            {
    
                DependencyProperty MyAttachedVisa = DependencyProperty.RegisterAttached ( "MyAttachedRegisterName", typeof ( string ), typeof ( SimpleClass ) );
                Order d = new Order ( );
                d.SetValue ( MyAttachedVisa, "Hello MyAttachedRegister" );
                string value2 = ( string ) d.GetValue ( MyAttachedVisa );
                Console.WriteLine ( value2 );
            }
    直接从附加属性存取数据

      看来,只要类是从DependencyObject派生的,它的对象都可以向容器里伸把手。

      回头再想想最前面那个神奇的Button和Grid,如何实现布局的呢?抛开看不到原理的静态快照,用代码来实现。

            public WindowTestAttachedProperty ( )
            {
                InitializeComponent ( );
    
                Grid grid = new Grid ( );
    
                grid.ColumnDefinitions.Add ( new ColumnDefinition ( ) );
                grid.ColumnDefinitions.Add ( new ColumnDefinition ( ) );
                grid.ColumnDefinitions.Add ( new ColumnDefinition ( ) );
    
                Button button = new Button ( );
                //可以用宿主的静态方法来设置
                Grid.SetColumn ( button, 1 );
                //也可以用订购者的实例方法来设置
                button.SetValue ( Grid.ColumnProperty, 1 );
    
                grid.Children.Add ( button );
                this.Content = grid;
            }
    代码实现附加属性调用

      那个神奇的现象在这里实现:grid.Children.Add ( button );

      布局对象先达好架子,为将来可能来到的子对象定义好区域。每个子对象被加入时,就给子对象分配位置。

      这个逻辑很简单,子对象中与布局相关的附加属性定义好后,在布局对象调用AddChildren方法时,

      这些属性值同样可以被布局对象获取到。那么用这些值去分配位置就好了。

      开辟一个容器,让宿主和订购者都可以存取里面的数据,就是这么一个技巧,被WPF做为核心技术,展示出众多神奇的现象。

      实际上却是要程序员放弃结构设计的原创权力,调用大量似是而非的糖衣,程序员做的事儿只是看上去象那么回事儿而已。

      崇拜它,你就永远也不知道它其实有多么普通。WPF用最白痴的技巧实现了-灵活与自由!

      有人送给WPF一个爱称-我佩服。于我而言,耗费一周的时间,最后发现,我研究的技术居然如此白痴-我喷饭!

  • 相关阅读:
    Saltstack module gem 详解
    Saltstack module freezer 详解
    Saltstack module firewalld 详解
    Saltstack module file 详解
    Saltstack module event 详解
    Saltstack module etcd 详解
    Saltstack module environ 详解
    Saltstack module drbd 详解
    Saltstack module dnsutil 详解
    获取主页_剥离百度
  • 原文地址:https://www.cnblogs.com/ww960122/p/4591850.html
Copyright © 2011-2022 走看看