首页 > 其他分享 >【环境属性AmbientValueAttribute】使用ShouldSerialize 和 Reset 方法定义默认值----------VS视图设计器开发

【环境属性AmbientValueAttribute】使用ShouldSerialize 和 Reset 方法定义默认值----------VS视图设计器开发

时间:2023-07-29 14:14:14浏览次数:37  
标签:Reset 控件 activateColor Color 视图 VS 默认值 属性

今天和大家讲解下关于winform控件的 环境属性AmbientValueAttribute 开发,net自带标准控件库里面的Control基类里面有些属性会根据父容器的属性变化而变化的,其中最常用环境属性包括 BackColor、ForeColor、Font、Cursor。在这里不得不吐槽微软把所有技术文档全放在一个网站,用他的搜索找资料就像大海捞针一样。环境属性 这个概念与功能的实现我足足找了两天才找到,还是在外网谷歌搜索电子书籍找到讲解,后来才找到官网对应文档网址。百度引擎全是不沾边的抄袭粘贴结果,真令人气愤。因为最近没啥心情可能写的比较乱,你慢慢理解吧因为这是winform控件开发很重要知识点。

我们用Label 控件来举个例子。“Text” 属性“普通属性”,“BackColor” 环境属性。当你修改窗体的 Text 属性值时窗体里面的 Label 控件的 Text 属性是不会发生变化的。但当你修改窗体 BackColor 属性时,你会发现 Label 控件的 BackColor 属性值会同时改变成和窗体 BackColor 属性值一样的值。

我们在使用net自带标准控件库里面的控件下,大家应该发现控件属性是有默认值的,我们在VS属性面板看到属性值如果是等于属性的默认值,属性面板显示的为本比较小,而且在Designer.cs文件或资源文件找不到对该属性赋值的代码。当我们在属性面板把属性值修改成其他值时会发现属性面的为本会变成粗体,而且能在Designer.cs文件或资源文件找到对该属性赋值的代码。  那VS是如何实现的呢,这里就要提到 “DefaultValueAttribute”默认值特性、“DesignerSerializationVisibility”生成代码类型特性、“ShouldSerialize”是否需要生成代码方法 、“Reset”重置属性值方法

1.当我们为属性添加DefaultValueAttribute 特性时,如果VS发现你在视图设计器属性面板修改属性值,而修改后的值与DefaultValueAttribute 特性设置的默认值不一样时,VS就会在Designer.cs文件或资源文件 添加对应属性值赋值代码。那这个特性什么时候适合使用呢,一般是在编写代码时就已经能确定默认值。因为它的参数只能时常量变量不行因为编译器在编译时就必须知道。

例子:

        private Color activateColor = Color.White;
        [DefaultValueAttribute(typeof(Color), "White")]
        public Color ActivateColor
        {
            get { return this.activateColor; }
            set{this.activateColor = value;}
        }

  

2.当我们确定某个属性只能在运行期间用来存放值,任何情况下不希望VS为它生成对应代码。这时候应该使用DesignerSerializationVisibility特性。

例子:

        private Color tmpColor = Color.White;
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public Color TmpColor
        {
            get { return this.tmpColor; }
            set { this.tmpColor = value; }
        }

  

 3。以上两个例子都是“普通属性”例子。他们利用默认值特性和代码生成类型特性告诉VS是否需要生成属性代码。下面是个“环境属性”例子。在下面例子中我们定义新控件TestControl,它新增 ActivateColor 的环境属性,这个属性的值会根据它的父容器的BackColor属性值改变而改变。现在我们把TestControl控件 添加到窗体上,我们把窗体的BackColor属性的值改成Red红色,这时候你可以可以发现TestControl控件的ActivateColor的属性值也变成Red红色,但是你查看Designer.cs文件的TestControl实例,他并没有生成一句 ...ActivateColor=Color.Red; 这样的代码。重点在于 ShouldSerializeActivateColor 这个方法。这个方法的存在就告诉了VS  ActivateColor是个环境属性,它发现独立存储值activateColor==Color.Empty意味值是从父容器对应属性获取的,所以没有生成对应属性代码。简单的说环境属性时通过属性get访问器、set访问器、和ShouldSerialize方法配合使用实现的。这种方式能够让我们灵活控制是否需要生成代码的逻辑开发。

3.1 用于判断是否为属性生成代码的方法命名有规范的 :ShouldSerialize+属性名称 就得出ShouldSerializeActivateColor方法,这个方法会被VS通过反射调用在ActivateColor属性身上。
3.2 用属性值重置方法命名有规范的 :Reset+属性名称 就得出ResetActivateColor方法,这个方法会被VS通过反射调用在ActivateColor属性身上。

例子:

        public class TestControl : Control
        {
            public readonly Color ActivateDefaultColor = Color.White;//预留默认值,因为颜色必须要有值。

            private Color activateColor = Color.White;//用于存放与默认值不一样的独立存储值

            /// <summary>
            /// 与BackColor属性关联的ActivateColor环境属性
            /// </summary>
            public Color ActivateColor
            {
                get
                {
                    // 1.设置过独立存储值
                    if (this.activateColor != Color.Empty)
                    {
                        return activateColor;
                    }

                    // 2.父容器控件的对应属性值
                    if (this.Parent != null)
                    {
                        return this.Parent.BackColor;
                    }

                    // 3.如果是ActiveX控件返回指定值(这个要根据自己实际情况,这部分代码省略,可以参考微软控件库Control.cs源码)

                    // 4.如果找到对应ISite,返回指定值(这个要根据自己实际情况,这部分代码省略,可以参考微软控件库Control.cs源码)

                    // 5.返回预留默认值
                    return ActivateDefaultColor;
                }
                set
                {
                    Color default_value = Color.Empty;//先找出属性当前默认值是什么
                    if (this.activateColor != Color.Empty)
                    {
                        default_value = activateColor;
                    }
                    else if (this.Parent != null)
                    {
                        default_value = this.Parent.BackColor;
                    }
                    //   else if (如果是ActiveX控件)
                    // {
                    //  default_value =返回指定值(这个要根据自己实际情况,这部分代码省略,可以参考微软控件库Control.cs源码)
                    //  }

                    // else if (如果找到对应ISite)
                    // {
                    //  default_value =返回指定值(这个要根据自己实际情况,这部分代码省略,可以参考微软控件库Control.cs源码)
                    //  }
                    else
                    {
                        default_value = ActivateDefaultColor;
                    }


                    if (value == default_value)
                        this.activateColor = Color.Empty;
                    else
                        this.activateColor = value;

                }
            }

            /// <summary>
            /// 如果activateColor不等于Color.Empty,这代表用户修改过属性值
            /// </summary>
            /// <returns></returns>
            private bool ShouldSerializeActivateColor()
            {
                return activateColor != Color.Empty;
            }

            /// <summary>
            /// VS属性面板属性右键菜单重置选项要把属性设置成该值
            /// </summary>
            private void ResetActivateColor()
            {
                ActivateColor = Color.Empty;
            }

        }

  

标签:Reset,控件,activateColor,Color,视图,VS,默认值,属性
From: https://www.cnblogs.com/tlmbem/p/17586429.html

相关文章

  • [odoo开发笔记05]odoo 15&16 Tree/看板视图添加按钮
    odoo在15及之后版本产生js引用变更,导致14及之前列表视图(Tree/List)添加自定义按钮的方式产生了变化。目前15/16版本列表视图添加按钮有三种方式1.每个明细行上都显示按钮此种Tree视图添加按钮仅需要定位第一个字段,添加button即可创建xml文件(例如sale_view.xml)写入以下内容<?......
  • Odoo Integer 字段类型在视图上不显示千分位
    OdooInteger字段类型会在视图上显示千分位。但我们有时候不需要显示千分位,可以如下处理:<fieldname="field"options="{'format':false}"/>这样就不会显示千分位了。......
  • ios 视图显示在最上面
    iOS视图显示在最上面在iOS开发中,视图是构建用户界面的基本组件。但是,在某些情况下,我们需要确保某个视图显示在其他视图的最上面,以便用户可以直接与它进行交互。本文将介绍如何将视图显示在最上面,并提供相应的代码示例。1.使用bringSubviewToFront方法UIView类提供了一个方法br......
  • mysql使用default给列设置默认值的问题
    add column会修改旧的默认值add column和modify column在default的语义上处理不一样。对于addcolumn,会将历史为null的值刷成default指定的值。而对于modifycolumn,只会对新数据产生影响,历史数据仍然会保持为null。结论:1. add column和modify column在default的语义上......
  • 关于视图类和序列化类的知识
    1.代码classPayOrderView(GenericViewSet):serializer_class=PaySerializerdefcreate(self,request,*args,**kwargs):ser=self.get_serializer(context={'request':request},data=request.data)ser.is_vaild(raise_exceptio......
  • mongodb创建了视图后会生成system.views,但是没有权限查询
    环境:OS:Centos7mongodb:5.0.19mongodb创建了视图后会生成system.views,但是没有权限查询myrepl:PRIMARY>db.system.views.find()Error:error:{"ok":0,"errmsg":"notauthorizedondb_pushmsgtoexecutecommand{find:\"sy......
  • microstation打开obj文件之后,默认是哪种视图?
     Obj其实一种mesh文件。。一整个obj是一整个mesh吗?能不能把不同的mesh进行分组,赋上名字,属性等信息。。这个信息存贮在.mtl文件里?还是存储在Obj里?......
  • uni-app vue-cli命令行创建项目,拉取模板(dcloudio/uni-preset-vue)失败,443超时报错
    安装vue/clinpminstall-g@vue/cli问题根据官网提示,通过vue-cli命令行创建项目,出现如下报错。Fetchingremotepresetdcloudio/uni-preset-vue...ERRORFailedfetchingremotepresetdcloudio/uni-preset-vue:ERRORRequestError:connectETIMEDOUT192.30.25......
  • 怎么在MYSQL显示默认值
    项目方案:在MySQL中显示默认值1.简介在MySQL中,可以为表的列设置默认值,以确保在插入新记录时,如果没有提供该列的值,将使用默认值作为替代。本项目旨在提供一个方案,用于在MySQL中显示默认值。2.实现方案2.1创建表格首先,我们需要创建一个包含默认值的表格。可以使用以下代码在My......
  • Django学习笔记:第四章django的视图
    1.视图函数用于处理客户端的请求并生成响应数据。在属兔中使用函数处理请求的方式,被称为视图函数,也叫作FBV(FunctionBaseViews).一个简单的视图函数:在views.py里面配置fromdjango.httpimportHttpResponse#导入HttpResponse类defindex(request):#接收HttpRequest......