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

    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依赖属性和附加属性


    
    
    
    
    
    
    
    
    
    
    展开全文
  • 属性

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

    万次阅读 2018-03-17 19:32:05
    数据集由数据对象组成,一个数据对象代表一个实体。...属性有不同类型:标称属性(nominal attribute)、二元属性(binary attribute)、序数属性(ordinal attribute)、 数值属性(numerical...
  • 多值属性、复合属性等概念

    千次阅读 2020-04-24 09:19:30
    多值属性、符合属性等概念 1).简单属性:不能再划分为更小部分的属性。 2).复合属性:可以再划分为更小的部分,也就是能再划分为一些其他属性属性。 比如说:name属性可被设计为一个包括first_name,middle_name,...
  • 函数属性 python中的函数是一种对象,它有属于对象的属性。除此之外,函数还可以自定义自己的属性。注意,属性是和对象相关的,和作用域无关。 自定义属性 自定义函数自己的属性方式很简单。假设函数名称为myfunc...
  • C#属性

    千次阅读 2007-03-24 13:49:00
    本节课将介绍C#属性,其目的包括:1.理解什么是属性2.如何实现属性3.创建一个只读属性4.创建一个只写属性属性C#中独具特色的新功能。通过属性来读写类中的域,这具有一定的保护功能。在其它语言中,这是通过实现...
  • C#属性和属性访问器

    2020-03-21 20:53:56
    导言:在C#中,对属性的封装,一个比较常见的方法是设置属性访问器。原文在此,我做了一些修改和增添,传送门在此。封装的意义在于保护或者防止代码(数据)被我们无意中破坏。在面向对象程序设计中数据被看作是一个...
  • C# 属性设置

    千次阅读 2020-07-03 13:44:17
    属性设置为对外访问只读,对内可写,同时设置默认值。举例: public string DL_PointA { get; private set; } = "2054325";
  • c# 属性

    千次阅读 2018-12-31 10:29:24
    属性是一种用于访问对象或类的特性的成员,可以表示对象的某一组成部分或者特性。 属性提供了一种机制,它把读取和写入对象的某些特性与一些操作关联起来。 可以像使用公共数据成员一样使用属性,但实际上他们是...
  • C#属性是域的扩展(即通常说的成员变量或字段等)它配合C#中的域(字段)使用,使之构造一个安全的应用程序,为什么说通过属性来替代域会提高应用程序的安全呢?  原因就在于C#属性通过访问器(Accessors)用进行数据访问...
  • C#属性是域的扩展(即通常说的成员变量或字段等)它配合C#中的域(字段)使用,使之构造一个安全的应用程序,为什么说通过属性来替代域会提高应用程序的安全呢? 原因就在于C#属性通过访问器(Accessors)用进行数据访问....
  • C#属性默认值设置

    千次阅读 2019-07-24 20:36:41
    C#属性默认值设置 关于在MVC中view中设置默认值,可以象如下设置: 1、关于VIEWMODEL的部分 如果是C# 6.0,网上资料查到说可以 public int X { get; set; } = 100 如果语法不支持,只能改回.net 2.0的写法。 ...
  • C#属性赋值

    2019-11-12 22:11:16
    属性类型,如果属性类型是C#中预定义的15种,直接赋值 整数8种 第二步 属性类型不属于预定义的15种,等号后面试着空格,如果出现智能提示,直接点,选择一个需要的选项分号结束 第三步 属性类型不是15种,...
  • c#属性之继承

    2012-03-08 15:36:41
    前一文章请参见http://space.itpub.net/9240380/viewspace-718062本节如下:public abstract class Vehicle { //属性的虚属性...
  • c# 属性与字段

    千次阅读 2018-06-06 15:15:50
    字段与属性都是类的成员。 字段是数据成员,是隶属于类的变量。 属性是函数成员,它不为数据存储分配内寸,它执行代码。 当字段为private,可以用属性来读写此字段。 代码如下 class C1 { private int ...
  • C# 属性的使用

    千次阅读 2018-06-07 09:51:43
    (转载自https://www.cnblogs.com/qikeyishu/p/7501185.html)1、属性的作用:保护字段,对字段取值与赋值进行限定2、属性的使用:_name(属性名)public [对应字段类型] 属性名Name{get{return _name;}set{_name=...
  • c#属性的定义

    千次阅读 2019-07-25 21:45:54
    1、什么是属性 属性是一种用于访问对象或类的特性的成员。 属性有访问器,这些访问器指定在他们的值被读取或者写入时所需要执行的语句。 我们知道的访问器有get访问器和set访问器两种 2、属性的声明 public class ...
  • C# 属性上方的标识符说明

    千次阅读 2014-09-19 16:02:09
    指定属性是否应该在属性窗口中显示,使用布尔值设置。一般情况下,对于常用的和比较重要的属性设置Browsable为true,否则,设置Browsable为false。  EditorBrowsable 设置属性在编辑器中的可见性,比如设置在...
  • C# 属性 set与get方法

    千次阅读 2016-01-13 16:07:25
    为了更好的隐藏数据成员,将对数据成员的存储与访问分离开,避免直接访问可能造成的错误,同时又具备使用数据成员的灵活性,我们用到了属性。对于属性的读写我们用到set和get。通过set方法来设置属性,get方法来获取...
  • C#属性有什么作用

    2016-10-01 18:14:00
    C#属性有什么作用 1,主要作用:将读,写权限分开。如果不使用属性,仅使用public, protected, private,这几个限制都是读,写属性一起的,可读就可写,不可读同时也不可写。不能实现只读不可写,只写不可读的...
  • C#属性的两种写法

    千次阅读 2015-08-18 16:55:44
    using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace 属性 { class Program { public class A { //////属性的方式一 // pri
  • c#属性的特点

    2008-06-30 20:51:00
    属性可以实现只读或只写,而域(成员变量)则不行. 属性的set方法可以针对用户给定的要求进行对value的检查,而域(成员变量)则不行. 属性的get方法可以返回经过计算过的值. 属性的实现就是方法的实现,可以定义抽象的属性...
  • C# 属性修改 触发某事件

    千次阅读 2017-03-07 19:59:34
    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Dynamic; using System.Linq; using System.Reflection;...using System.Tex
  • 为何C#属性名称的首字母要大写

    千次阅读 2008-04-15 11:08:00
    最近因工作需要参与了一个.Net小 项目,语言使用C#,虽然这语言很多地方来源于Java,然而搞Java久了来搞C#还真有一点不习惯,其中一个最不习惯的是C#中的属性首字母大小。比如:public class Topic ...{ private...
  • 最近研究自定义控件,在控件中添加了自定义的结构属性之后,自定义控件就会报错,如下图: 网上有个高手说把 *.resx 文件中的...删除掉就行了。我试了一下,报错的确是没有了,但是我的控件的属性就变成NULL了...
  • C# 属性值的特性验证样例

    千次阅读 2019-01-27 12:07:51
    public abstract class AbstractAttribute : Attribute {  public AbstractAttribute()  {  }  public abstract bool Validate(object Value);  }  public class DataLengthAtr...
  • C#属性_赋值私有字段

    千次阅读 2020-09-13 17:41:36
    C#属性_定义私有字段 为类中字段手写Get方法和Set方法很麻烦, 所以程序帮我们自动的封装出这个两个方法:属性 属性是这样的成员:它提供灵活的机制来读取、编写或计算某个私有字段的值。 可以像使用公共数据成员...

空空如也

1 2 3 4 5 ... 20
收藏数 5,663,523
精华内容 2,265,409
关键字:

属性