精华内容
参与话题
问答
  • 属性

    2019-10-01 14:58:47
    字段和属性的选择原则 1.字段和属性的使用形式仅能是下面两种形式  (1)使用自动属性,无字段  (2)显示定义支持字段,并为该字段提供带逻辑代码的属性. 2.字段的访问性肯定是private 3.仅仅当set和get访问器里面...

    字段和属性的选择原则

    1.字段和属性的使用形式仅能是下面两种形式

      (1)使用自动属性,无字段

      (2)显示定义支持字段,并为该字段提供带逻辑代码的属性.

    2.字段的访问性肯定是private

    3.仅仅当set和get访问器里面包含逻辑代码时,才会使用字段.

    自动属性

    public string Name { get; set; }
    public int Age { get; set; }

    C#编译器会自动创建字段,且提供默认值:0,“”, null,false。

    访问级别不对等的get,set

    public string Name { get; private set; }

    我们可以在这个类的构造函数等其他函数中赋值或获取Name。在外界只能使用get。

    只读属性

    public string Name { get;}

    只能在构造函数中为其赋值,类的其他函数只能get之。  在外界只能使用get。

    接口属性

    public interface ISampleInterface
    {
        // Property declaration:
        string Name
        {
            get;
            set;
        }
    }

    接口属性的访问器没有正文。 因此,访问器的用途是指示属性为读写、只读还是只写。

    属性的访问修饰符

    对属性或索引器使用访问修饰符受以下条件的制约:

    • 不能对接口或显式接口成员实现使用访问器修饰符。

    • 仅当属性或索引器同时具有 set 和 get 访问器时,才能使用访问器修饰符。 这种情况下,只允许对其中一个访问器使用修饰符。

    • 如果属性或索引器具有 override 修饰符,则访问器修饰符必须与重写的访问器的访问器(如有)匹配。

    • 访问器的可访问性级别必须比属性或索引器本身的可访问性级别具有更严格的限制。

    重写属性或索引器时,被重写的访问器对重写代码而言必须是可访问的。 此外,属性/索引器及其访问器的可访问性都必须与相应的被重写属性/索引器及其访问器匹配。

     

     

    将不带 set 访问器的属性视为只读。 将不带 get 访问器的属性视为只写。 将具有以上两个访问器的属性视为读写。

    与字段不同,属性不会被归类为变量。 因此,不能将属性作为 ref 或 out 参数传递。

    属性可以是读-写属性(既有 get 访问器又有 set 访问器)、只读属性(有 get 访问器,但没有 set 访问器)或只写访问器(有 set 访问器,但没有 get 访问器)。 只写属性很少出现,常用于限制对敏感数据的访问。

    get 访问器必须以 return 或 throw 语句结尾,且控件不能超出访问器正文。

     

    属性具有许多用途:它们可以先验证数据,再允许进行更改;可以在类上透明地公开数据,其中数据实际是从某个其他源(如数据库)检索到的;可以在数据发生更改时采取措施,例如引发事件或更改其他字段的值。

    可以通过使用 static 关键字将属性声明为静态属性。 这使属性可供调用方在任何时候使用,即使不存在类的任何实例。

    转载于:https://www.cnblogs.com/zhenguan/p/11309386.html

    展开全文
  • 类的属性和方法(内置方法)

    千次阅读 2018-01-10 23:03:34
    一、类的属性 1.类的组成由属性和方法组成,属性可以称为成员变量,方法可以称为成员函数。 2.对象的创建,创建对象的过程称之为实例化。当一个对象被创建后,包含三个方面的特性:1.对象句柄 2.属性 3.方法。...
    一、类的属性
    1.类的组成由属性和方法组成,属性可以称为成员变量,方法可以称为成员函数。
    2.对象的创建,创建对象的过程称之为实例化。当一个对象被创建后,包含三个方面的特性:1.对象句柄 2.属性 3.方法。
    句柄:用于区分不同的对象。
    对象的属性和方法与类中的成员变量和成员函数对应。
    在类里面的属性和方法叫做成员变量和成员函数,在实例化后,调用这些变量和函数,就叫做对象属性和对象方法。
    3.类的属性,类的属性按使用范微分为公有属性和私有属性,类的属性范围取决于属性的名称。
    公有属性:在类中和类外都能调用的属性。
    私有属性:不能在类外以及类以外的函数调用。
    私有属性的定义方式:以__双下划线开始的成员变量就是私有属性,可以通过instance.classname_attribute方式访问。
    内置属性:由系统在定义类的伤害默认添加的,有前后双下划线构成,__dict__, __module__。
    比如:
    class People(object):
        color = 'yellow'  #这就是一个公有属性,可以在类里和类外调用
        __age = 30       #这就是一个私有属性,只能在类里调用。
        def think(self):   
            self.color = "black"    
            print "i am a %s" % self.color
            print "i am a thinker"
      print(self.__age)    #调用age
    ren = People()
    print ren.color
    ren.think() 
    print(ren.__age)
    可以看到在类里调用的__age成员变量可以调用出来,但是在类外就不行了。
    如果想在外面看到的话可以这么看。但是不一般不建议这么做,在调试的时候可以用。
    class People(object):
           color = 'yellow'
         __age = 30
        def think(self):
            self.color = 'black'
            print(self.color)
    ren = People()
    print ren.color
    ren.think()
    print ren.__age
    print ren._People__age  #这就可以看到内部的属性。还是建议放在成员函数里使用。

    使用内部属性这么做直接使用对象属性的方式调用。
    print ren.__dict__ 是属性所以没有括号。

    把公有属性分成字典的类型了。
    我们不光可以使用对象来访问类的属性,还可以通过类来访问类的属性。但是只能访问公有属性。
    print people.color

    4.对象属性修改。
    class People(object):
           color = 'yellow'
         __age = 30
        def think(self):
            self.color = 'black'
            print(self.color)
    ren = People()
    ren.color = “白色人”   #通过对象属性修改color的值
    print ren.color
    ren.think()
    print ren._People__age


    可以发现,对象属性的值得变了,但是在类中的的属性的值没有改变还是yellow。
    通过类名去访问内置属性
    print People.__dict__

    可以发现打印出了类里的所有属性对应的值。

    二、类的方法
    1.类的方法的定义和定义函数一样,但是需要self作为第一个参数,这个是必须要有的。self方法就是用来区分函数和类方法的。
    类的方法分为:1.公有方法 2.私有方法 3.类方法 4.静态方法
    公有方法:在类中和类外都可以调用的方法。和公有属性一样
    私有方法:不能被类外部调用,在方法前面加上__双下划线就是私有方法。和私有属性一样。
    类方法:被classmethod()函数处理过的函数,能被类所调用,也能被对象所调用(是继承的关系)
    静态方法:相当于“全局函数”,可以被类直接调用,可以被所有实例化对象共享,通过staticmethod()定义,静态方法没有self参数。
    2.可不可以通过类名调用方法呢?直接使用时不行的。必须要使用对象来调用。
    People.think()

    3.如果要把方法变成一个类方法我们需要使用一个函数来处理一下

    使用classmethod()函数来处理一下,我们需要通过一个变量来接收一下,这样就可以访问test方法了。只要方法名字就可以了,不用加括号。
    其实这种方式,我们还可以理解为动态方法,因为在调用的时候没有去加载其他方法出来。只有我们在调用的方法中,调用了其他方法才开会去加载。所以说是个动态,通过类来访问方法,加载的资源很少。
    4.静态方法的定义。
    如果我们直接写一个不加self的方法,是不行会报错,会当成类方法,提示你需要有一个参数。
    def test():
    print "test"

    直接用类去调用也是不行。

    我们需要一个函数去处理一下。
    sm = staticmethod(test) 调用的时候也是通过这个接收的变量名去访问,

    虽然看上去定义的方式差不多,但是运行机制是不一样的,静态方法调用的伤害,因为没有self这个参数,所以会把类里的所有变量都加载进内存。
    但是运行速度要比动态的快。
    那么静态方法如何去访问类里的成员变量呢?
    如果使用self.color是不行的会报错。使用类名.属性的方式访问。
    def test():
    print People.color

    因为self 就代表类的本身,静态方法没有self 这个参数,就使用类名来访问。
    5.其实还有一种方式可以去访问类方法和静态方法。使用装饰器。
    装饰器如何使用?
    @staticmethod
    def test():
    print "this is a static method"
    People.test()

    装饰器就是@后面加处理的函数名,在方法的上方加装饰器,只对装饰器下面的这一个函数起作用。

    这种方式就比较简便。

    三、Python的内部类
    1.所谓内部类,就是类的嵌套,就是在类的内部在定义类。主要目的是为了更好的抽象现实世界。
    就像os模块,os.path.altsep 这就想内部类,通过OS的外部类.path内部类.去调用属性和方法:
    2.定义内部类和使用内部类
    第一种方式:直接使用外部类调用内部类:
    class People(object):
        color = 'yellow'
        __age = 30
        class chinese(object):   #定义了一个内部类
            print "i am chinese"
            
        def think(self):
            self.color = 'black'
            print(self.color)
        def test():
            print 'Testing...'
        sm = staticmethod(test)
    jack = People.chinese()   #第一种方式实例化内部类。
    在内部类定义一个属性,如何访问呢。
    name = "i am a chinese"

    直接使用对象属性来访问。
    但是这种方式外部类的属性和访问就调用不了了。
    第二种方式:先对外部类进行实例化,然后再实例化内部类。
    class People(object):
        color = 'yellow'
        __age = 30
        class chinese(object):   #定义了一个内部类
            print "i am chinese"
            
        def think(self):
            self.color = 'black'
            print(self.color)
        def test():
            print 'Testing...'
        sm = staticmethod(test)
    ren = People()  #先实例化外部类
    jack = ren.Chinese()  #在实例化内部类,实例化内部类需要加上“外部类名字.内部类名字”
    print jack.name
    

    这样就是可以调用内部类的属性和方法和外部类的属性和方法了。
    第三种方式:直接使用外部类加内部类加内部类属性来访问
    class People(object):
        color = 'yellow'
        __age = 30
        class chinese(object):   #定义了一个内部类
            print "i am chinese"
            
        def think(self):
            self.color = 'black'
            print(self.color)
        def test():
            print 'Testing...'
        sm = staticmethod(test)
    print People.Chinese.name  #使用类的方法来访问。
    print People.Chinese().name  #使用对象的方法来访问,其实这就是第一种方式的实例化内部类了。

    3.类的内置方法,又称魔术方法
    1.__str__(self)内置方法
    先看实例化后对象的返回结果。
    class People(object):
            color = 'yellow'
            __age = 30
            class Chinese(object):
                name = "i am a chinese"
            def __str__(self):
               return "This is a People object"
            def think(self):
                   self.color = 'black'
                   print(self.color)
               # print(self.__age)
             @classmethod
              def test1(self):
                   print("this is a class method")
              @staticmethod
               def test():
                   print "this is static method"
       ren = People()
       print ren

    使用__str__方法后的结果

    可以看到输出变了。而且不用去调用__str__内置方法。在运行的时候就直接加载了。__str__内置方法只能用给return ,不能用print。
    2.构造函数和析构函数
    构造函数:用于初始化类的内部状态,Python中提供的构造函数是__init__()
    析构函数:用于释放对象占用的资源,Python中提供析构函数的是__del__()
    首先来看下构造函数。
     class People(object):
            color = 'yellow'
            __age = 30
            class Chinese(object):
                name = "i am a chinese"
            def __str__(self):
                return "This is a People object"
      def __init__(self):
     self.color = 'red'
            def think(self):
                   self.color = 'black'
                   print(self.color)
               # print(self.__age)
             @classmethod
              def test1(self):
                   print("this is a class method")
              @staticmethod
               def test():
                   print "this is static method"
       ren = People()
       print ren.color   #通过对象访问就变成了red
       print People.color  #通过类属性访问还是没变。

    这个函数也是自动执行,当我们实例化类的时候就会自动执行。
    通常我们用这个构造方法来修改参数。通过对象访问的属性会根据我们传的值不同属性会改变。而根据类的这种方式是不变的。
    构造函数可以放属性和方法,而且不需要调用就可以加载出来。
    class People(object):
            color = 'yellow'
            __age = 30
            class Chinese(object):
                name = "i am a chinese"
            def __str__(self):
                return "This is a People object"
      def __init__(self,c='green'):
     self.color = c
     self.think()
            def think(self):
                   self.color = 'black'
                   print(self.color)
               # print(self.__age)
             @classmethod
              def test1(self):
                   print("this is a class method")
              @staticmethod
               def test():
                   print "this is static method"
       ren = People()
       print ren.color   
       print People.color  
    析构函数:在脚本执行的最后来执行__del__内置方法。用于结束占用的资源
    class People(object):
        color = 'yellow'
        __age = 30
        class Chinese(object):
            name = "i am a chinese"
        def __str__(self):
            return "This is a People object"
        def __init__(self):
            print "init...."
            self.fd = open('1.txt')  #打开一个文件
            self.think()
        def think(self):
            self.color = 'black'
            print(self.color)
        @classmethod
        def test1(self):
            print("this is a class method")
        @staticmethod
        def test():
            print "this is static method"
        def __del__(self):
            print "del...."
            self.fd.close()  #关闭回收
    ren = People()
    print ren.color
    print People.color
    print "Main end" 

    可以看到del这个内置方法是在脚本结束后才执行的。
    3.其实在Python中del这个内置方法是可选的。如果不提供,Python会在后台提供默认的析构函数。
    Python有一个垃圾回收机制,使用gc模块释放不在使用的对象。采用引用计数的算法方式来处理回收。可以使用gc.collect()方法一次性收集所有待处理的对象。

    展开全文
  • HTML标签及常见属性

    千次阅读 2019-04-19 09:48:01
    属性有自定义属性和通用属性(全局属性:每个标签都能去使用)两种 属性id是唯一标识,不可重复(例如:身份证号码) 属性class可以重复(例如:名字) div占据当前父级元素的一整行 di...

     

    body主体里一般会存在的内容:

    图片,文字,超链接,音频,视频,

     

    date-info="123" :此属性属于自定义的属性,属性名和值都可随意定

     

     

    属性有自定义属性和通用属性(全局属性:每个标签都能去使用)两种

     

    属性id是唯一标识,不可重复(例如:身份证号码)

    属性class可以重复(例如:名字)

    div占据当前父级元素的一整行

    dir属性:

    dir="ltr":左对齐  

    dir="rtl":右对齐

    Tab键自动补齐:直接书写英文,按tab键,标签会自动补齐

     

     

    注:用快捷键打出h1-h6标签:h${要写的内容$}*要打印的个数

    -----再按Tab键

    -----再按Tab键

     

     

    text-indent:首行缩进   2em两个字符

    不设置高度是因为文字会自动换行

     

    a标签跳转:

    target="_blank"表示重新打开一个窗口进行显示

    target="_self"表示在原窗口进行显示

    href="调转地址",可以调转到已有的网站界面,也可以调转到自己写的界面

     

     

     

     

     

     

     

    src="图片地址(可以是绝对路径,也可以是相对路径)"

    alt是当图片因为一些原因加载不出来时就会显示alt里的内容

    可以用style对图片进行高度与宽度的限制

    border边框,颜色自动默认位黑色,没有单位

     

    span的宽度和高度都是由内容进行挤压填充的(不会自动换行,写满之后自动换行)

    div的宽度和高度与父级元素一致(一个div就是一行)

    span和div没有语义

     

    border-color:red  设置水平线的颜色,但是原本的黑色不能去掉

    <b>对字体进行加粗,不是语义化标签

    <strong>对字体进行加粗,是语义化标签

    <i>斜体,没有语义

    <em>斜体,是语义标签,起着重强调作用

     

    <s>删除,没有语义

    <del>删除,有语义

     

    <u>下划线,没语义化

    <ins>下划线,有语义化

     

     

     

     

     

     

    两张图片并列:(浮动)

     

     

     

     

     

     

     

     

     

     

     

     

    展开全文
  • 依赖属性和附加属性

    千次阅读 2017-10-20 14:56:41
     刚着手开始学习C#的时候,不明白为什么会有属性这个东西,不是已经有了字段了吗,你说属性里面有get和set方法对数据进行了封装,可以通过对方法的访问限定来控制该属性是否可以被赋值,但是不也有readonly这个...

        重混江湖后的第一篇文章,竟然有些手生......(惶恐+惭愧)ing,怕是套路也要有些变化了-_-


    一.属性

        刚着手开始学习C#的时候,不明白为什么会有属性这个东西,不是已经有了字段了吗,你说属性里面有get和set方法对数据进行了封装,可以通过对方法的访问限定来控制该属性是否可以被赋值,但是不也有readonly这个关键字可以用来修饰字段吗,你又说可以通过在get或set方法里面对数据进行一系列的操作来对数据进行限制,可以将数据的获取和赋值分开进行不同的处理,好吧这个我是服气的。

    你可以这样子写(写prop再按两次Tab就自动生成了):

    public int Age { get; set; }       //则就是个很普通的属性了
    public int Age { get; }       //可以不写set方法,等同于通过访问限定符private来对set方法进行修饰

    还可以这样写:

            private int _age;
            public int Age
            {
                get { return _age; }
                //这就比单纯的字段对数据的处理要来得自由
                private set
                {
                    if (value < 0 || value > 100)
                        return;
                    _age = value;
                }
            }
    其实这都是很基础的东西了,但还是觉得此处应有个引入,直接上货怕有些干......

    那下面要切入正题了——>


    二.依赖属性

        呐,名字里都有个属性说明它就是个属性,只是这个属性在方法里封装处理的并不是普通的字段,而是类型为DependencyProperty的一个对象,我们可以先来看它的普通写法(propdp按一次Tab自动生成,好方便的说):

            public int MyProperty
            {
                get { return (int)GetValue(MyPropertyProperty); }
                set { SetValue(MyPropertyProperty, value); }
            }
    
            //下面的注释是自动生成的,可以看到这个对象就是用于MyProperty的封装数据,它可以作用于动画,样式,绑定等等......
            // Using a DependencyProperty as the backing store for MyProperty.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty MyPropertyProperty =
                DependencyProperty.Register("MyProperty", typeof(int), typeof(ownerclass), new PropertyMetadata(0));

    上面的MyProperty属性这里不做解释,看一下MyPropertyProperty,这里要说明的是依赖属性的命名约定为以Property作为后缀,该对象使用了DependencyProperty类里面的Register静态方法的返回值:




    可以看到Register方法有三个重载,前三个参数

    • String:表示所要对其进行封装的属性的名称;
    • 第一个Type:表示该属性所属类型;
    • 第二个Type:表示该属性所有者的类型,也就是在哪个类里面定义的这个依赖属性;
    后面的参数,PropertyMetadata对象



    这个对象里面包含有依赖属性的元数据相关的信息,元数据也就是一些用来描述类型的信息,这里包含例如属性默认值通知回调和验证回调的引用,还有一些框架性特征(布局、数据绑定等),其中参数:

    • Object:表示要对该属性指定的默认值,例如string类型可以指定default(string);
    • PropertyChangedCallback:从名字就可以看出,这是一个在属性值被更改时所调用的回调函数,常用于绑定数据变更时处理;
    • CoerceValueCallback:Coerce意思是胁迫、强制,也就是这个方法用于在对属性值进行改变的时候,对赋值进行检查,强制对值进行赋值,返回值为Object类型,这个才是要赋给属性的值;
    Register方法的最后一个参数是ValidateValueCallback,这个方法同样是对值的检查,该方法如下:
    public delegate bool ValidateValueCallback(object value)
    传入的参数value为Object类型,也就是要进行检查的属性值,这里会不会有疑问,既然已经有了CoerceValueCallback方法可以对值进行检查之后强制改变要进行的赋值,为什么还要有这个合法值得检查?因为CoerceValueCallback方法无论如何检查,返回值为Object,都会给属性值进行一个赋值,然后会调用PropertyChangedCallback方法,但是在进行CoerceValueCallback方法的调用之前,就会调用ValidateValueCallback方法对值进行检查,可以看到该方法的返回值为一个bool类型,当值满足条件时返回true,这时就会去调用CoerceValueCallback对值进行进一步的处理,如果不满足条件的话返回false,则本次赋值失败告终,根本就没有后续CoerceValueCallback什么事,也就是ValidateValueCallback方法是值更新前检查方法,对值进行的最初的拦截检查,可以看如下图:



    所以,在对依赖属性进行注册的时候可以根据需要选择不同的Register方法和Parameter构造器,实现需要的方法来对数据进行处理;

    前面讲了一堆,可能没有接触的人还会觉得云里雾里,或者说那些东西我看教程都会用,到底为什么要有依赖属性这么个东西?
    在进行WPF桌面编程的时候,我们都会用到各种各样的控件,这些控件都有一个高台阶似的继承关系,控件中的属性也都是一层层继承下来的,如果都是普通属性的话,每个属性在每个类中都是需要占有一定字节数,可能有些属性并不会被用到,但还是会保留从父类那里继承来的初始值,这样的话,到了底层的类就会有对象膨胀的问题,所以写到这里你应该可以想到依赖属性就是解决这个问题的吧,当然了,不然我说这些是为了铺垫晚饭吃什么吗-_-
    依赖属性是如何解决普通属性因为继承带来的对象膨胀的问题就是接下来要研究的依赖属性的原理:
    那就从最直观的使用DependencyProperty.Register方法来切入,Register注册,注册什么呢,注册属性数据啊,你不是因为继承每个基类里面都会有一份属性吗,那就将这些属性从类里面剥离出来,放到一个公共的区域,如果有需要就去里面进行值的注册,获取的时候去公共区里面查找,这不是很方便吗,没有用到的属性就不往里放,问题是不是就解决了?那好,我们用图解来说明:


    这里的公共区是一个全局字典,里面用来存放所有的依赖属性,其中:

    • Key是关键词,这个是在注册方法里面由所给的属性名和所属类进行哈希异或得到的哈希值;
    • value很好理解,就是每一个属性所有值;
    • index这个东西,因为每个依赖属性都是静态的,当进行注册之后相同的依赖属性只会在字典中保存一份,如果一个值更改那么其他所拥有者的值也会相应的进行更改,这显然不是我们所期望的,所以,真正进行存储的时候,全局字典中只会存储注册时候给的初始值,而对于其他通过继承方式得到该依赖属性并对其进行赋值的时候,其实是存储在一个单独的链表中,链表的存储对象中才存放每一个拥有者所赋的不同的值,哎呀看图吧:


    上图中的index是相同的,每一次进行值操作的时候,会现在全局的字典中通过Key值拿到对应的Property数据,获取其中的index,然后通过在链表中进行对应的index查找,如果找到了就使用链表中的值,如果没有就使用本身的默认值;

    那,如果我并不想要父类的那个依赖属性,我想把它变成自己的,也换一个默认值怎么办?重载咯:



    把Type换成自己的类,重新指定PropertyMetadata就好了,这其实是在字典中重新注册了一个依赖属性,也可以通过这个方法重新写该属性的元数据;

    那,我另外的一个类也想使用那个依赖属性,就只能通过继承的方式吗,我只是想用一个属性而已啊,要按其他不需要的也都继承下来吗?没这个必要啊:



    通过DependencyProperty的AddOwner方法,就可以把那个属性变为自己可以使用的了,同样也可以更改其默认值,也是在字典中重新注册了一个依赖属性;

    差不多吧,主要要说的就是这些,剩下的依赖属性的使用,比如在动画啊,样式或者绑定什么的都是另外的话了,哦还有优先级什么的,后续有需要再补充吧。


    三.附加属性

    简单讲,附加属性就是依赖属性,但它存在的意义是什么呢,先看写法:

    public static readonly DependencyProperty MyPropertyProperty = DependencyProperty.RegisterAttached(
      "MyProperty",
      typeof(Boolean),
      typeof(MyClass),
      new FrameworkPropertyMetadata());
    public static void SetMyProperty(UIElement element, Boolean value)
    {
      element.SetValue(MyPropertyProperty, value);
    }
    public static Boolean GetMyProperty(UIElement element)
    {
      return (Boolean)element.GetValue(MyPropertyProperty);
    }
    可以看到除了注册方法是RegisterAttached之外还有另外独立出来的静态方法SetValue和GetValue,在这里RegisterAttached和Register方法并没有什么不同,都是往全局字典中添加属性;

    但是可以看到在两个方法中有传入参数UIElement,所以有人说“依赖属性是给自己用的,附加属性是给别人用的”,这句话是没错的,在使用附加属性的时候回将使用者的信息作为参数传入进来,所以会有一些布局控件例如Grid,Canvas等有附加属性,Grid.SetRow和Canvas.SetLeft都是直接调用了静态的方法,通过传入的参数来告知属性所有者是谁用了我的属性,把它设为了什么值,这样在布局的时候我就知道要把谁往哪里放,这也是依赖属性和附加属性的一个区别。而且像这样单独将两个方法暴露出来也是为了方便他人使用。

    至于其他方面,其实都是一样的。


    四.栗子时间

    前面讲了那么多,都不如直接上个栗子看的实在(我也实在是写累了):

    假设这里有个需求,需要在TextBox里面填写年龄,默认值为成年18岁,但是不能超过100岁,也不能低于18岁,也就是有如下需求:

    • 有默认值
    • 有上下限
    • 有值检查
    • 有错误提醒
    而且有个儿童的勾选项,当选择了儿童之后,默认值就要更改为1,且上下限为1~18,如果取消勾选项恢复为成人设定,这里设计如下:
    C#后台代码:
        public partial class MainWindow
        {
            public MainWindow()
            {
                InitializeComponent();
    
                SetTextBinding();
            }
    
            private void SetTextBinding()
            {
                var binding = new Binding
                {
                    Source = this,
                    Path = new PropertyPath("MyAge")
                };
                TestTextBox.SetBinding(TextBox.TextProperty, binding);
            }
    
            public int MyAge
            {
                get { return (int)GetValue(MyAgeProperty); }
                set { SetValue(MyAgeProperty, value); }
            }
    
            //这里注册一个MyAge的依赖属性用于前台绑定,指定默认值为18
            public static readonly DependencyProperty MyAgeProperty =
                DependencyProperty.Register("MyAge", typeof(int), typeof(MainWindow),
                    new PropertyMetadata(18, PropertyChangedCallback, CoerceValueCallback), ValidateValueCallback);
            
            //当赋值成功的时候就改变TextBox的边框颜色
            private static void PropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
            {
                var window = dependencyObject as Window;
                var textBox = window?.FindName("TestTextBox") as TextBox;
                if (textBox != null) textBox.BorderBrush = Brushes.Cyan;
            }
    
            //当进行赋值的时候,如果值不在18~100之间,强制将值恢复为18,表示该值不合要求
            private static object CoerceValueCallback(DependencyObject dependencyObject, object baseValue)
            {
                var value = (int)baseValue;
                return value < 18 ? 18 : value;
            }
            
            //在开始赋值前对值进行检查,如果值超过100就弹个错误框显示
            private static bool ValidateValueCallback(object o)
            {
                var value = (int)o;
                if (value > 100)
                    MessageBox.Show("年龄有点大哈");
                return value < 100;
            }
    
            //当儿童选项被勾选的时候去更改属性的元数据
            private void ChildCheckBox_OnChecked(object sender, RoutedEventArgs e)
            {
                ChildAge.Instance.ChangeMetadata(sender);
            }
    
            //当取消勾选的时候,应该恢复为原来的属性值绑定才能正确显示
            private void ChildCheckBox_OnUnchecked(object sender, RoutedEventArgs e)
            {
                SetTextBinding();
            }
        }
    
        //重新定义一个Child类继承MainWindow
        public class ChildAge : MainWindow
        {
            public static ChildAge Instance
            {
                get { return _instance ?? (_instance = new ChildAge()); }
            }
    
            private static ChildAge _instance;
    
            private static Window _containerWindow;
            public void ChangeMetadata(object sender)
            {
                var item = sender as CheckBox;
                if (item == null) return;
    
                //更改属性元数据,默认值为1,对应的值处理检查方法也需重新定义
                MyAgeProperty.OverrideMetadata(typeof(ChildAge),
                    new PropertyMetadata(1, ChildAgePropertyChangedCallback, ChildCoerceValueCallback));
    
                ///这里因为前台数据是和后台绑定的,因此如果对应的属性改变了,前台绑定的源也应该随之改变
                _containerWindow = GetWindow(item);
                if (_containerWindow != null)
                {
                    var binding = new Binding
                    {
                        Source = this,
                        Path = new PropertyPath("MyAge")
                    };
                    var textBox = _containerWindow.FindName("TestTextBox") as TextBox;
                    textBox?.SetBinding(TextBox.TextProperty, binding);
                }
            }
    
            private static object ChildCoerceValueCallback(DependencyObject dependencyObject, object baseValue)
            {
                var value = (int)baseValue;
                return (value < 1 || value >= 18) ? 1 : value;
            }
    
            private static void ChildAgePropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
            {
                var textBox = _containerWindow?.FindName("TestTextBox") as TextBox;
                if (textBox != null) textBox.BorderBrush = Brushes.DarkGreen;
            }
        }
    
    
    
    
    
    
    前台如下设计:



    程序运行结果如下:


    至此结束对依赖属性和附加属性的讨论,如果对该文章有任何疑问或者有错误之处请及时指出,蟹蟹。
    更多更详细的内容可以参见MSDN:MSDN依赖属性和附加属性


    
    
    
    
    
    
    
    
    
    
    展开全文
  • 上一篇文章:HTML5–常见的新属性(前)表单相关属性这里涉及到的标签,包括form标签、input...新增属性主要包括以下几种: autocomplete novalidate和formnovalidate autofocus form formaction formenctype formmetho
  • 属性

    2019-03-14 23:37:34
    属性集 Properties 类表示了一个持久的属性集。Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。 java.util.Properties extends HashTable&lt;k,v&gt; implements Map&...
  • 多值属性、复合属性等概念

    千次阅读 2020-04-24 09:19:30
    多值属性、符合属性等概念 1).简单属性:不能再划分为更小部分的属性。 2).复合属性:可以再划分为更小的部分,也就是能再划分为一些其他属性属性。 比如说:name属性可被设计为一个包括first_name,middle_name,...
  • 【Java基础】属性编辑器PropertyEditor

    千次阅读 2018-05-12 22:03:30
    在Spring配置文件里,我们往往通过字面值为Bean各种类型的...我们可以隐约地感觉到一定有一个转换器在其中起作用,这个转换器就是属性编辑器。 “属性编辑器”这个名字可能会让人误以为是一个带用户界面的输入器...
  • 在Spring配置文件里,我们往往通过字面值为Bean各种类型的属性提供...我们可以隐约地感觉到一定有一个转换器在其中起作用,这个转换器就是属性编辑器。  “属性编辑器”这个名字可能会让人误以为是一个带用户界面的
  • 前文:  本章节会对InspectorEditor(属性编辑器)... 一个InspectorEditor(属性编辑器)产生直接对应着一个继承MonoBehaviour的脚本文件,脚本文件中定义着不同的属性以供InspectorEditor(属性编辑器)去实现。我
  • (注:这个曾发表在某Blog上,那个马上要没了,你懂的=。=) SSH相信很多整过J2EE的人都很熟悉,但可能很多人没有深入研究过其底层架构,我觉得其中spring的源码是记得详细研究的,如果能对其IOC,AOP的整个流程有...
  • spring的属性编辑器及如何自定义

    千次阅读 2008-12-20 12:01:00
     但诸如date之类,就需要自定义属性编辑器解决。 spring中的属性编辑器:1.属性编辑器本身是由Java提供了,Spring只是利用了这一特性使装配一个Bean更容易而已。2.应用场景(如以下例子中):如果有一个pojo类Demo....
  • spring中注入时间日期(java.util.Date)类型的属性的时候不能直接注入Date类型,需要进行类型转换。 1、编写UtilDatePropertyEditor类import java.beans.PropertyEditorSupport; import java.text....
  • 前言:如果我们单纯通过代码去修改图片的属性,非常复杂,我们希望有一个交互性界面实现修改图片,这是可以的,就是利用属性编辑器去修改,以2020a为例: 打开一个figure 点击查看 点击属性编辑器 这就是那个...
  • 基于属性编辑器框架

    千次阅读 2010-09-17 00:18:00
    看了Ogitor的代码后, 自己又实践了一把, 结合N3中学到的一些技巧, 在编辑器中得到了验证. 虽说做的是场景编辑器, 但是其它编辑器也可以用的, 毕竟思想都差不多. 对于一个编辑器, 通常是由一个个的"实体"组成, 或者...
  • spring中的属性编辑器

    2010-06-10 18:07:00
    spring中的属性编辑器:1.属性编辑器本身是由Java提供了,Spring只是利用了这一特性使装配一个Bean更容易而已。2.应用场景(如以下例子中):如果有一个pojo类Demo.java,其只有一个java.util.Date类型的属性,代码如下...
  • 修改单个文件的属性时直接在该属性窗口中修改即可,但当我们需要批量修改多个对象的属性时,就需要借助属性编辑器(Property Editor)。 启动属性编辑器 点击Tools-&amp;gt;Property Editor打开属性编辑器...
  • wpf编辑器属性栏和动态中英双语

    千次阅读 2013-01-08 17:15:59
    属性栏通过wpfPropertyGrid改写,实现了界面自定义,属性类型自定义和属性编辑自定义 中英双语用wpf的动态资源绑定来实现。
  • [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Content)]  public List QueryWinNames  {  get { return _gueryWinNames; }  set { _gueryW
  • JS获取元素属性和自定义属性

    万次阅读 2017-09-14 10:19:02
    获取元素的属性分为两种类型:1-获取元素常见的属性(class,id,type,value……)2-获取自定义的元素的属性(data-value,data-mess…….)获取元素的属性,设置元素的属性: 1-原生JS** 设置属性 .setAttribute(...
  • 1、打开ADSI编辑器,连接到对应的Active Directory 2、打开Active Directory选择创建一... 3、在ADSI编辑器列表中找到所创建的测试账号,点击右键属性打开属性编辑器页面,根据Value可以查询到各个值对应的Attribute
  • 本篇讲解了音频剪辑,节点数组,互斥面板,自定义类型的属性定义方法。关注我的公众号 darkpalm,回复【ts属性】即可获取源码
  • 问题: 现在这样一种需求, 有一个bean它的属性是java.util.Date类型,...可以说spring的属性编辑器和类型转换器都是做类型转换的,但属性编辑器多为string转其它类型, 方法1: 添加属性编辑器: class="org.sp
  • spring中配置bean属性的细节

    万次阅读 2020-01-20 03:57:04
    spring配置中属性也可以用标签代替例如value属性可以用<value></value>标签代替 value中的特殊字符用 <![CDATA[字面值]]> property标签的ref属性建立bean之间的引用关系 可以在property标签内...
  • springmvc属性编辑器: 对于日期类型的属性转换通过注入属性编辑器。可以在action类中通过@Binder注解注册属性编辑器。通过自定义属性编辑类方法,定义属性编辑器。 定义方法: 需要实现implements Converter, ...
  • Android 深入理解Android中的自定义属性

    万次阅读 多人点赞 2015-04-13 10:42:00
    对于自定义属性,大家肯定都不陌生,遵循以下几步,就可以实现: 自定义一个CustomView(extends View )类 编写values/attrs.xml,在其中编写styleable和item等标签元素 在布局文件中CustomView使用自定义的属性...
  • Delphi 给自定义控件添加属性

    千次阅读 2011-09-30 20:26:31
    1、属性编辑器和控件属性的关联函数: RegisterPropertyEditor函数:它用来注册一个属性编辑器,将控件中的一个属性和编辑器关联起来。 procedure RegisterPropertyEditor(PropertyType: PTyp
  • 为自己的属性编写一个编辑器

    千次阅读 2004-08-06 17:42:00
    网上经常有这样的问题:在设计控件时,怎样让自己的属性属性窗口中显示的时候加一个“…”按钮或者下拉列表框,然后通过自定义的编辑器来编辑该属性的值。我举一个常见的例子,假设你的属性是表示一个路径,你希望...
  • Python:类的继承,调用父类的属性和方法基础详解

    万次阅读 多人点赞 2018-12-30 11:35:01
    以下案例均表示Son类继承父类的一些属性和初始化参数构造等。 5个模块: (1):直接调用父类属性方法; (2):重写父类属性方法; (3):强制调用父类私有属性方法; (4):调用父类的__init__方法 (5)...
  • HTML属性

    千次阅读 2018-03-28 11:07:01
    HTML属性HTML属性包含了元素的额外信息,它总是出现在HTML开始标签中,并且,通常以名/值对的形式出现(空属性除外,它可以只有属性没有值)。属性的名称和值是大小写无关的,推荐使用小写。HTML属性的值有以下四种...

空空如也

1 2 3 4 5 ... 20
收藏数 5,563,247
精华内容 2,225,298
关键字:

属性