博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

asp.net组件(9)简单属性与复杂属性

Posted on 2007-12-20 21:03  a-peng  阅读(688)  评论(0编辑  收藏  举报
新建一个网页.拉入一个Button控件.
选中该控件查看属性编辑器:

从图中可以看出有多种属性方式.
     简单属性:
        BorderWidth,CssClass等等. 
     复杂属性 (可折叠)
        Font其下有好多个属性
            Bold,Name等等.
我们对其设置一下,查看它的属性有何特别之处
<asp:Button
ID="Button1" ->简单
runat="server" ->简单
Text="Button" ->简单
BackColor="Silver" ->简单
Font-Bold="True" ->复杂
Font-Names="Arial" ->复杂
/>
         
简单属性我们可以很好理解.就如前些篇中做的控件.在其中声明一个属性.就可以做出这种效果.
但复杂属性如何做到呢?

按我们的思路,应该是先有一个Font对象或结构体,然后其下又有一些属性.恩.试试.
不对呀,那样写出来的不成了 Button1.Font.Bold 或 Button1.Font.Names
那怎么做到和简单属性那样:Button1.Text 或 Button1.Font-Bold呢?

我已经开题了.今天就是讲这个.当然我们有更伟大的目标.那就看下去吧.
现在我们就来做这种类型的控件 目标:
<cc1:properitycomponent id="ProperityComponent1" runat="server" 
  University="闽江学院" 
  UniversityAddress-Provinces="福建" 
  UniversityAddress-City="福州">
</cc1:properitycomponent>

实现代码:
using System;
using System.ComponentModel;
using System.Web.UI;

namespace WebComponent
{
    
//大学所在地址类
    public class Address
    
{
        
public Address()
        
{}

        
private string _provinces;//所在省份
        private string _city;//所在城市

        
public string Provinces
        
{
            
get
            
{
                
return _provinces;
            }

            
set
            
{
                _provinces 
= value;
            }

        }


        
public string City
        
{
            
get
            
{
                
return _city;
            }

            
set
            
{
                _city 
= value;
            }

        }

    }


    
public class ProperityComponent : Control
    
{
        
private string _university;//大学名称
        private Address _universityAddress = new Address();//大学地址

        
public string University
        
{
            
get
            
{
                
return _university;
            }

            
set
            
{
                _university 
= value;
            }

        }


        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        
public Address UniversityAddress
        
{
            
get
            
{
                
return _universityAddress;
            }

        }


        
protected override void Render(HtmlTextWriter writer)
        
{
            System.Text.StringBuilder sb 
= new System.Text.StringBuilder();
            sb.Append(
"大学名称:" + University + "<br />");
            sb.Append(
"所在省份:" + UniversityAddress.Provinces + "<br />");
            sb.Append(
"所在城市:" + UniversityAddress.City);

            writer.Write(sb.ToString());
            
//base.Render(writer);
        }

    }

}


唯一与以前做的有差别的地方,就是在UniversityAddress属性的前面加了个标签.
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public Address UniversityAddress
{
    
get
    
{
      
return _universityAddress;
    }

}
这个标签有什么作用呢?
它表示代码生成器将序列化属性的子属性而不是它本身,怎么理解呢?
就是说Button控件的Font属性中的Bold和Underline子属性
将被序列化为(Font-Underline="True" Font-Bold="True)这种形式.

这个控件中就是将 ProperityComponent控件中的UniversityAddress属性中的Provinces和City子属性.
序列化为(UniversityAddress-Provinces="福建"和UniversityAddress-City="福州")这种形式.

到这里成功第一步了.

接下来,我们想得到属性编辑器的更多帮助
我们也想像Font属性那样,可以展开.点下就能修改,多方便
那么在UniversityAdress属性前再加上TypeConverter(typeof(ExpandableObjectConverter))
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        [TypeConverter(
typeof(ExpandableObjectConverter))]
        
public Address UniversityAddress
        
{
            
get
            
{
                
return _universityAddress;
            }

        }
这个标签有什么作用呢?
就是将UniversityAddress这个属性 TypeConverter 类型转化为 Expandable 可展开的类型
 就是完成图片上的功能.
这里需要说明一下:属性编辑器的默认类型都是文本框. 就像City的后面,只能输入文本.

为了加深对TypeConverter的理解.我们为上面的控件加上一个功能.
即大学的主题颜色,一听到这个.
大家脑子中会不会有一个念头,不会要我输入颜色的值#ffffff吧,那我可不干.
对呀,那要是也像Button中的BackColor那种属性多好,点一下,就可以出来颜色选择框.
对这就是我们的目标.
using System;
using System.Drawing;
using System.ComponentModel;
using System.Web.UI;

namespace WebComponent
{
    
//大学所在地址类
    public class Address
    
{
        
public Address()
        
{}

        
private string _provinces;//所在省份
        private string _city;//所在城市

        
public string Provinces
        
{
            
get
            
{
                
return _provinces;
            }

            
set
            
{
                _provinces 
= value;
            }

        }


        
public string City
        
{
            
get
            
{
                
return _city;
            }

            
set
            
{
                _city 
= value;
            }

        }

    }


    
public class ProperityComponent : Control
    
{
        
private string _university;//大学名称
        private Address _universityAddress = new Address();
        
private Color _color;//大学的主题颜色

        
public string University
        
{
            
get
            
{
                
return _university;
            }

            
set
            
{
                _university 
= value;
            }

        }


        [TypeConverter(
typeof(System.Web.UI.WebControls.WebColorConverter))]
        
public Color Color
        
{
            
get
            
{
                
return _color;
            }

            
set
            
{
                _color 
= value;
            }

        }


        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        [TypeConverter(
typeof(ExpandableObjectConverter))]
        
public Address UniversityAddress
        
{
            
get
            
{
                
return _universityAddress;
            }

        }


        
protected override void Render(HtmlTextWriter writer)
        
{
            System.Text.StringBuilder sb 
= new System.Text.StringBuilder();
            sb.Append(
"大学名称:" + University + "<br />");
            sb.Append(
"大学主题颜色:" + Color.ToString() + "<br />");
            sb.Append(
"所在省份:" + UniversityAddress.Provinces + "<br />");
            sb.Append(
"所在城市:" + UniversityAddress.City);

            writer.Write(sb.ToString());
            
//base.Render(writer);
        }

    }

}


大家注意到了没有.在Color属性上面我们做了些什么呢?
[TypeConverter(typeof(System.Web.UI.WebControls.WebColorConverter))]
将Color属性转化为 WebColorConverter.这些什么Converter
都是从System.ComponentModel.TypeConverter派生来的.所以后面都会加个Converter
就是它让我们实现了下面这张这么神奇的东西


试着在属性面板编辑City和Provinces,修改好后然后运行页面,发现并没有显示出我们修改后的值.
这就怪了.哪里出问题了?

在那两个子属性上方加上[NotifyParentProperty(true)].然后再运行试试.
    //大学所在地址类
    public class Address
    
{
        
public Address()
        
{}

        
private string _provinces;//所在省份
        private string _city;//所在城市

        [NotifyParentProperty(
true)]
        
public string Provinces
        
{
            
get
            
{
                
return _provinces;
            }

            
set
            
{
                _provinces 
= value;
            }

        }


        [NotifyParentProperty(
true)]
        
public string City
        
{
            
get
            
{
                
return _city;
            }

            
set
            
{
                _city 
= value;
            }

        }

    }

行啦!!!Notify parent property从子属性往父级通知一个更改.明白了吧.

到这里本该结束这一篇的.因为有点长了.但是觉得应该放在一块讲的东西分开了可不好.
<asp:DropDownList>
    <asp:ListItem></asp:ListItem>
</asp:DropDownList>
看看这个,帅吧.是内镶的就应该是内镶的.为何要勉强把它放到外面去呢!
<cc1:ProperityComponent ID="ProperityComponent1" runat="server"
University="闽江学院" UniversityAddress-Provinces="福建" UniversityAddress-City="福州">
            <UniversityAddress Provinces="福建" City="福州"></UniversityAddress>
</cc1:ProperityComponent>
看看这家伙长的多俊呀..这就是我们的目标.支持两种形式.
最好是有嵌套时,显示嵌套的,也就是让嵌套的优级比较高.
[PersistenceMode(PersistenceMode.InnerProperty)]
这个标签有个功能,就是让某个属性能够具有嵌套的功能.

PersistenceMode决定持久化属性方式,默认为[PersistenceMode(PersistenceMode.Attribute)]
表示持久化属性为主标签的属性,如果属性包含子属性,则子性持久化成破折号连接的样式,
比如Font的子属性,Font-Name代表Font.Name子属性;

[PersistenceMode(PersistenceMode.InnerProperty)]表示用嵌套标签表示复杂属性,
比如asp:DropDownList中的 asp:ListItem,就使用嵌套的子标签的形式来持久化。

知道了这个之后,我们还需要让页面能够知道控件嵌套的内容表示的是属性.
怎么办呢?在控件前加上[ParseChildren(true)]

使用该特性指示当在页上以声明方式使用控件时,
嵌套在服务器控件标记内的XML元素是应该视为属性还是应视为子控件。
通常情况下,包含两种声明方式:
ParseChildren(true),表示将子XML元素作为服务器控件的属性分析
ParseChildren(false),表示将子XML元素作为服务器控件的子控件分析

即:用于告知页面分析器把控件标记中的内容解析为属性(true)还是子控件(false)

最后一步.我们希望得到属性编辑器的支持
[PersistChildren(false)]
说明:该特性指示设计时是否应将服务器控件的子控件作为内部嵌套控件保持。
PersistChildren(true),则将服务器控件的子控件作为嵌套服务器控件标记保持。
PersistChildren(false),则将该控件的属性作为嵌套元素保持。

即:用于告知设计器把控件标记中的内容保存为属性(false)还是子控件(true)

一般设计具有嵌套功能的控件时.
会使用12+13
[ParseChildren(true)]
[PersistChildren(false)]
MyControl:Control


好.结束.看完整代码.

using System;
using System.Drawing;
using System.ComponentModel;
using System.Web.UI;

namespace WebComponent
{
    
//大学所在地址类
    public class Address
    
{
        
public Address()
        
{}

        
private string _provinces;//所在省份
        private string _city;//所在城市

        [NotifyParentProperty(
true)]
        
public string Provinces
        
{
            
get
            
{
                
return _provinces;
            }

            
set
            
{
                _provinces 
= value;
            }

        }


        [NotifyParentProperty(
true)]
        
public string City
        
{
            
get
            
{
                
return _city;
            }

            
set
            
{
                _city 
= value;
            }

        }

    }


    [ParseChildren(
true)]
    [PersistChildren(
false)]
    
public class ProperityComponent : Control
    
{
        
private string _university;//大学名称
        private Address _universityAddress = new Address();
        
private Color _color;//大学的主题颜色

        
public string University
        
{
            
get
            
{
                
return _university;
            }

            
set
            
{
                _university 
= value;
            }

        }


        [TypeConverter(
typeof(System.Web.UI.WebControls.WebColorConverter))]
        
public Color Color
        
{
            
get
            
{
                
return _color;
            }

            
set
            
{
                _color 
= value;
            }

        }


        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        [TypeConverter(
typeof(ExpandableObjectConverter))]
        [PersistenceMode(PersistenceMode.InnerDefaultProperty)]
        
public Address UniversityAddress
        
{
            
get
            
{
                
return _universityAddress;
            }

        }


        
protected override void Render(HtmlTextWriter writer)
        
{
            System.Text.StringBuilder sb 
= new System.Text.StringBuilder();
            sb.Append(
"大学名称:" + University + "<br />");
            sb.Append(
"大学主题颜色:" + Color.ToString() + "<br />");
            sb.Append(
"所在省份:" + UniversityAddress.Provinces + "<br />");
            sb.Append(
"所在城市:" + UniversityAddress.City);

            writer.Write(sb.ToString());
            
//base.Render(writer);
        }

    }

}


如果对其中的一些常用标签还不是很熟悉.可以查看.
组件(1)http://www.cnblogs.com/a-peng/archive/2007/12/17/1003306.html