前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >DropDownList下拉框多选

DropDownList下拉框多选

作者头像
跟着阿笨一起玩NET
发布2018-09-18 15:24:26
14.3K0
发布2018-09-18 15:24:26
举报

最近弄完个项目、项目需要支持多选功能、找了很多例子没找到合适的,最后自己开发了个控件:

DropDownCheckBoxList 控件继承 DropDownList ;

整个控件由四部分组成:一个文本框、两个图标(向下|向上)、一个隐藏的 DIV 、两个隐藏域。控件示意图

收缩状态:

展开状态:

先介绍些关键属性:

1. DisplayMode 有两个值 Label,Value;分别表示显示文本、显示值。

2. Splitor 多选时,多个值间的分隔符。

3. ShowSelectAllOption 是否显示" 全选 " 选项、一般多项选择都会有个" 全选 " 功能。

4. SelectAllOptionLabel 全选选项显示的文本,默认值:"全选"。

重写了 OnInit 事件,在 OnInit 事件里面创建控件:

  protected override void OnInit(EventArgs e)         {             base.OnInit(e);             if (!DesignMode)             {                 CreateControls();             }         }

代码语言:javascript
复制
 1  protected void CreateControls()
 2         {
 3             txt = new TextBox();
 4             txt.ID = this.ClientID + "_txtMain";
 5             txt.ReadOnly = true;
 6             txt.Width = (Unit)(this.Width.Value - 20);
 7             txt.Style.Add(HtmlTextWriterStyle.Padding, "0");
 8             txt.Style.Add(HtmlTextWriterStyle.Margin, "0");
 9             txt.Height = this.Height;
10 
11             if (txt.Height.IsEmpty)
12             { txt.Height = 15; }
13 
14             hfValueText = new HiddenField();
15             hfValueText.ID = string.Format("{0}_{1}", this.ClientID, "selectItemValueText");
16             hfValue = new HiddenField();
17             hfValue.ID = string.Format("{0}_{1}", this.ClientID, "selectItemValue");
18 
19             txt.Enabled = this.Enabled;
20         }

在预呈现 OnPreRender 事件里面注册客户端脚本:

protected override void OnPreRender(EventArgs e)         {             base.OnPreRender(e);             if (!DesignMode)             {                 DoRegisterScript();             }         }

代码语言:javascript
复制
 1 ClientScriptManager sc = this.Page.Page.ClientScript;
 2 
 3             string scriptString = sc.GetWebResourceUrl(this.GetType(), "DevControl.Resources.DropDownCheckBoxList.js");
 4 
 5             if (!sc.IsClientScriptIncludeRegistered("DropDownGridScriptKey"))
 6             { sc.RegisterClientScriptInclude(this.GetType(), "DropDownGridScriptKey", scriptString); }
 7 
 8             scriptString = Page.Form.Attributes["onclick"];
 9             if (string.IsNullOrEmpty(scriptString))
10             { scriptString = string.Format("responseOnFormClick(event,'{0}');", this.ClientID); }
11             else
12             { scriptString = string.Format("{0} responseOnFormClick(event,'{1}');", scriptString, this.ClientID); }
13 
14             Page.Form.Attributes.Add("onclick", scriptString);
15 
16             this.Page.RegisterRequiresPostBack(this);

重写 TagKey 设置为:Table

protected override HtmlTextWriterTag TagKey         {             get             {                 if (!DesignMode)                 {                     return HtmlTextWriterTag.Table;                 }                 return base.TagKey;             }         }

在 AddAttributesToRender 事件中 设置 table 的属性

 protected override void AddAttributesToRender(HtmlTextWriter writer)         {             if (!DesignMode)             { AddCustomAttribute(writer); }             else             { base.AddAttributesToRender(writer); }         }

代码语言:javascript
复制
1 writer.AddAttribute(HtmlTextWriterAttribute.Width, this.Width.ToString());
2             writer.AddAttribute(HtmlTextWriterAttribute.Border, "0");
3             writer.AddAttribute(HtmlTextWriterAttribute.Id, this.ClientID + "_displaytable");
4             writer.AddAttribute(HtmlTextWriterAttribute.Cellpadding, "0");
5             writer.AddAttribute(HtmlTextWriterAttribute.Cellspacing, "0");
6             writer.AddStyleAttribute(HtmlTextWriterStyle.Position, "relative");
7             writer.AddStyleAttribute(HtmlTextWriterStyle.ZIndex, "1");
8             writer.AddStyleAttribute(HtmlTextWriterStyle.Left, "-5px");

在 GetDivWidth 方法里面动态算出 DIV 宽度,避免当某项内容长度超出 DIV 的默认宽度时,动态调整DIV 的宽度。

代码语言:javascript
复制
 1 int itemWidth = 0;
 2             int byteCount = 0;
 3             foreach (ListItem item in this.Items)
 4             {
 5                 byteCount = System.Text.UnicodeEncoding.Default.GetByteCount(item.Text);
 6                 if (byteCount > itemWidth)
 7                 { itemWidth = byteCount; }
 8             }
 9 
10             itemWidth = itemWidth * 8 + 20;
11             itemWidth = itemWidth + 16; //加上checkbox 宽度
12 
13             if (itemWidth > this.Width.Value)
14             { this.Width = itemWidth; }

在 RenderContents 事件里面呈现默认显示(文本框、图标)的内容:

protected override void RenderContents(HtmlTextWriter writer)         {             if (DesignMode)             {                 base.RenderContents(writer);                 return;             }             RenderCustomContent(writer);         }

代码语言:javascript
复制
 1 void RenderCustomContent(HtmlTextWriter writer)
 2         {
 3             GetDivWidth();
 4             string divId = this.ClientID + "_div";
 5             string cmbDown = this.ClientID + "_imgDown";
 6             string cmbUp = this.ClientID + "_imgUp";
 7 
 8             // base.RenderContents(writer);
 9             ////控件显示主体
10             writer.AddAttribute(HtmlTextWriterAttribute.Align, "left");
11             writer.RenderBeginTag(HtmlTextWriterTag.Tr);
12             writer.RenderBeginTag(HtmlTextWriterTag.Td);
13             writer.AddStyleAttribute(HtmlTextWriterStyle.Cursor, "default");
14             if (this.Enabled)
15             { writer.AddAttribute(HtmlTextWriterAttribute.Onclick, string.Format("toggleDivShowState('{0}','{1}','{2}');", this.ClientID, Splitor, this.Items.Count)); }
16             ////控件主体文本框 
17             txt.RenderControl(writer);
18 
19             writer.Write("<br/>");
20             ////隐藏下拉面板
21             writer.AddAttribute(HtmlTextWriterAttribute.Id, divId);
22             writer.AddStyleAttribute(HtmlTextWriterStyle.Display, "none");
23             writer.AddStyleAttribute(HtmlTextWriterStyle.BackgroundColor, "#ECECE3");
24             writer.AddStyleAttribute(HtmlTextWriterStyle.Position, "absolute");
25             writer.AddStyleAttribute(HtmlTextWriterStyle.ZIndex, "32766");
26             writer.AddStyleAttribute(HtmlTextWriterStyle.BorderColor, "Gray");
27             writer.AddStyleAttribute(HtmlTextWriterStyle.BorderWidth, "thin");
28             writer.AddStyleAttribute(HtmlTextWriterStyle.BorderStyle, "double");
29             writer.AddStyleAttribute(HtmlTextWriterStyle.VerticalAlign, "top");
30             writer.AddStyleAttribute(HtmlTextWriterStyle.Width, this.Width.ToString());
31             writer.RenderBeginTag(HtmlTextWriterTag.Div);
32             ////呈现 item 列表
33             ModifyRenderedCheckboxes(writer);
34             writer.RenderEndTag();//end div
35 
36             writer.RenderEndTag();//end td
37             ////下拉图标
38             writer.AddAttribute(HtmlTextWriterAttribute.Border, "0");
39             writer.RenderBeginTag(HtmlTextWriterTag.Td);
40             writer.AddStyleAttribute(HtmlTextWriterStyle.Margin, "0");
41             writer.AddStyleAttribute(HtmlTextWriterStyle.Padding, "0");
42             writer.AddStyleAttribute(HtmlTextWriterStyle.Position, "relative");
43             writer.AddStyleAttribute(HtmlTextWriterStyle.Left, "-8px");
44             writer.AddAttribute(HtmlTextWriterAttribute.Src, this.Page.ClientScript.GetWebResourceUrl(this.GetType(), "DevControl.Resources.cmb_down.jpg"));
45 
46             if (this.Enabled)
47             { writer.AddAttribute(HtmlTextWriterAttribute.Onclick, string.Format("toggleDivShowState('{0}','{1}','{2}');", this.ClientID, Splitor, this.Items.Count)); }
48 
49             writer.AddAttribute(HtmlTextWriterAttribute.Id, cmbDown);
50             writer.RenderBeginTag(HtmlTextWriterTag.Img);
51             writer.RenderEndTag();//end img
52             writer.AddStyleAttribute(HtmlTextWriterStyle.Margin, "0");
53             writer.AddStyleAttribute(HtmlTextWriterStyle.Padding, "0");
54             writer.AddStyleAttribute(HtmlTextWriterStyle.Position, "relative");
55             writer.AddStyleAttribute(HtmlTextWriterStyle.Left, "-8px");
56             writer.AddAttribute(HtmlTextWriterAttribute.Src, this.Page.ClientScript.GetWebResourceUrl(this.GetType(), "DevControl.Resources.cmb_up.jpg"));
57             if (this.Enabled)
58             { writer.AddAttribute(HtmlTextWriterAttribute.Onclick, string.Format("toggleDivShowState('{0}','{1}','{2}');", this.ClientID, Splitor, this.Items.Count)); }
59             writer.AddStyleAttribute(HtmlTextWriterStyle.Display, "none");
60             writer.AddAttribute(HtmlTextWriterAttribute.Id, cmbUp);
61             writer.RenderBeginTag(HtmlTextWriterTag.Img);
62             writer.RenderEndTag();//end img
63 
64             writer.RenderEndTag();//end td
65             writer.RenderEndTag();//end tr 
66         }

在 ModifyRenderedCheckboxes 方法里面呈现 DIV 的内容:

代码语言:javascript
复制
  1 protected void ModifyRenderedCheckboxes(HtmlTextWriter writer)
  2         {
  3             int index = 0;
  4 
  5             string spanId = "";
  6             string wapperId = "";
  7             string allChkId = "";
  8 
  9             writer.AddAttribute(HtmlTextWriterAttribute.Width, this.Width.ToString());
 10             writer.AddAttribute(HtmlTextWriterAttribute.Border, "0");
 11             writer.AddAttribute(HtmlTextWriterAttribute.Id, this.ClientID + "_Optiontable");
 12             writer.AddAttribute(HtmlTextWriterAttribute.Cellpadding, "0");
 13             writer.AddAttribute(HtmlTextWriterAttribute.Cellspacing, "0");
 14             writer.AddStyleAttribute(HtmlTextWriterStyle.Position, "relative");
 15             writer.AddStyleAttribute(HtmlTextWriterStyle.Left, "0px");
 16             writer.RenderBeginTag(HtmlTextWriterTag.Table);
 17 
 18             #region 首选项
 19             if (ShowSelectAllOption)
 20             {
 21                 writer.RenderBeginTag(HtmlTextWriterTag.Tr);
 22                 wapperId = string.Format("{0}_{1}", this.ClientID, "chkAllItemWapper");
 23                 allChkId = string.Format("{0}_{1}", this.ClientID, "chkAllItemValue");
 24                 spanId = string.Format("{0}_{1}", this.ClientID, "chkAllItemText");
 25 
 26                 writer.AddAttribute("onmouseover", string.Format("setStyleOnMouseOver('{0}');", wapperId));
 27                 writer.AddAttribute("onmouseout", string.Format("setStyleOnMouseOut('{0}');", wapperId));
 28 
 29                 writer.AddStyleAttribute(HtmlTextWriterStyle.Width, (this.Width.Value - 10).ToString());
 30                 writer.AddStyleAttribute(HtmlTextWriterStyle.Height, "20px");
 31                 writer.AddAttribute(HtmlTextWriterAttribute.Id, wapperId);
 32                 writer.AddStyleAttribute("cursor", "pointer");
 33                 writer.AddStyleAttribute("cursor", "hand");
 34                 writer.AddStyleAttribute(HtmlTextWriterStyle.VerticalAlign, "middle");
 35                 writer.AddStyleAttribute(HtmlTextWriterStyle.PaddingLeft, "5px");
 36                 writer.AddStyleAttribute(HtmlTextWriterStyle.PaddingRight, "5px");
 37                 writer.AddAttribute(HtmlTextWriterAttribute.Onclick, string.Format("return clickChangeValueWhenCheckAllCheckBox(event,'{0}','{1}');", allChkId, this.ClientID));
 38                 writer.RenderBeginTag(HtmlTextWriterTag.Td);
 39                 writer.AddAttribute(HtmlTextWriterAttribute.Id, allChkId);
 40                 writer.AddStyleAttribute("cursor", "pointer");
 41                 writer.AddStyleAttribute("cursor", "hand");
 42                 writer.AddAttribute(HtmlTextWriterAttribute.Value, "");
 43                 writer.AddStyleAttribute(HtmlTextWriterStyle.VerticalAlign, "middle");
 44                 writer.AddStyleAttribute(HtmlTextWriterStyle.PaddingBottom, "5px");
 45                 writer.AddAttribute(HtmlTextWriterAttribute.Onclick, string.Format("return mouseUpdateValueWhenSelectAllStateChanged(event,this,'{0}');", this.ClientID));
 46                 writer.AddAttribute(HtmlTextWriterAttribute.Type, "checkbox");
 47                 writer.RenderBeginTag(HtmlTextWriterTag.Input);
 48                 writer.RenderEndTag();//end input
 49 
 50                 writer.AddAttribute(HtmlTextWriterAttribute.Id, spanId);
 51                 writer.AddStyleAttribute(HtmlTextWriterStyle.FontSize, "small");
 52                 writer.AddStyleAttribute(HtmlTextWriterStyle.PaddingTop, "5px");
 53                 writer.AddStyleAttribute(HtmlTextWriterStyle.VerticalAlign, "middle");
 54                 writer.AddStyleAttribute(HtmlTextWriterStyle.PaddingBottom, "5px");
 55                 writer.AddAttribute(HtmlTextWriterAttribute.Onclick, string.Format("return mouseUpdateValueWhenCheckAllCheckBox(event,'{0}','{1}');", allChkId, this.ClientID));
 56                 writer.RenderBeginTag(HtmlTextWriterTag.Span);
 57                 writer.Write(SelectAllOptionLabel);
 58                 writer.RenderEndTag();//end span
 59 
 60                 writer.RenderEndTag();//td
 61                 writer.RenderEndTag();//tr
 62             }
 63             #endregion
 64 
 65             #region 内容选项
 66             string chkId = "";
 67             foreach (ListItem item in this.Items)
 68             {
 69                 writer.RenderBeginTag(HtmlTextWriterTag.Tr);
 70                 wapperId = string.Format("{0}_{1}{2}", this.ClientID, "chkItemWapper", index.ToString());
 71                 chkId = string.Format("{0}_{1}{2}", this.ClientID, "chkItemValue", index.ToString());
 72                 spanId = string.Format("{0}_{1}{2}", this.ClientID, "chkItemText", index.ToString());
 73 
 74                 writer.AddAttribute("onmouseover", string.Format("setStyleOnMouseOver('{0}');", wapperId));
 75                 writer.AddAttribute("onmouseout", string.Format("setStyleOnMouseOut('{0}');", wapperId));
 76 
 77                 writer.AddStyleAttribute(HtmlTextWriterStyle.Width, (this.Width.Value - 10).ToString());
 78                 writer.AddStyleAttribute(HtmlTextWriterStyle.Height, "20px");
 79                 writer.AddAttribute(HtmlTextWriterAttribute.Id, wapperId);
 80                 writer.AddStyleAttribute("cursor", "pointer");
 81                 writer.AddStyleAttribute("cursor", "hand");
 82                 writer.AddStyleAttribute(HtmlTextWriterStyle.VerticalAlign, "middle");
 83                 writer.AddStyleAttribute(HtmlTextWriterStyle.PaddingLeft, "5px");
 84                 writer.AddStyleAttribute(HtmlTextWriterStyle.PaddingRight, "5px");
 85 
 86                 writer.AddAttribute(HtmlTextWriterAttribute.Onclick, string.Format("return clickChangeValueWhenCheckItemCheckBox(event,'{0}','{1}','{2}','{3}');", chkId, spanId, allChkId, this.ClientID));
 87                 writer.RenderBeginTag(HtmlTextWriterTag.Td);
 88                 writer.AddAttribute(HtmlTextWriterAttribute.Id, chkId);
 89                 writer.AddStyleAttribute("cursor", "pointer");
 90                 writer.AddStyleAttribute("cursor", "hand");
 91                 writer.AddStyleAttribute(HtmlTextWriterStyle.PaddingTop, "5px");
 92                 writer.AddStyleAttribute(HtmlTextWriterStyle.VerticalAlign, "middle");
 93                 writer.AddStyleAttribute(HtmlTextWriterStyle.PaddingBottom, "5px");
 94                 writer.AddAttribute(HtmlTextWriterAttribute.Width, "16px");
 95                 writer.AddAttribute(HtmlTextWriterAttribute.Value, item.Value);
 96                 writer.AddAttribute(HtmlTextWriterAttribute.Onclick, string.Format("return mouseUpdateValueWhenCheckItemStateChanged(event,'{0}','{1}','{2}','{3}');", chkId, spanId, allChkId, this.ClientID));
 97                 writer.AddAttribute(HtmlTextWriterAttribute.Type, "checkbox");
 98                 writer.RenderBeginTag(HtmlTextWriterTag.Input);
 99                 writer.RenderEndTag();//end input
100 
101                 writer.AddAttribute(HtmlTextWriterAttribute.Id, spanId);
102                 writer.AddStyleAttribute(HtmlTextWriterStyle.FontSize, "small");
103                 writer.AddStyleAttribute(HtmlTextWriterStyle.PaddingTop, "5px");
104                 writer.AddStyleAttribute(HtmlTextWriterStyle.VerticalAlign, "middle");
105                 writer.AddStyleAttribute(HtmlTextWriterStyle.PaddingBottom, "5px");
106                 writer.AddAttribute(HtmlTextWriterAttribute.Onclick, string.Format("return mouseUpdateValueWhenCheckItemCheckBox(event,'{0}','{1}','{2}','{3}');", chkId, spanId, allChkId, this.ClientID));
107                 writer.RenderBeginTag(HtmlTextWriterTag.Span);
108                 if (DisplayMode == DevControl.DisplayMode.Label)
109                 { writer.Write(item.Text); }
110                 else
111                 { writer.Write(item.Value); }
112 
113                 writer.RenderEndTag();//end span
114 
115                 writer.RenderEndTag();//td
116                 writer.RenderEndTag();//tr
117                 index++;
118             }
119             #endregion
120 
121             writer.RenderBeginTag(HtmlTextWriterTag.Tr);
122             writer.RenderBeginTag(HtmlTextWriterTag.Td);
123             hfValue.RenderControl(writer);
124             hfValueText.RenderControl(writer);
125             writer.RenderEndTag();//end td
126             writer.RenderEndTag();//end tr
127             writer.RenderEndTag();//end table
128         }

在 LoadPostData 事件里面获取选择的内容:

protected override bool LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection)         {             if (!DesignMode)             {                 this.txt.Text = postCollection[txt.ID];                 this.hfValue.Value = postCollection[hfValue.ID];                 this.hfValueText.Value = postCollection[hfValueText.ID];                 return true;             }             return base.LoadPostData(postDataKey, postCollection);         }

定义个枚举类型 DisplayMode  表示显示"文本或值"

[Serializable]     public enum DisplayMode     {         /// <summary>         /// 显示文本         /// </summary>         Label,         /// <summary>         /// 显示值         /// </summary>         Value     }

客户端脚本 DropDownCheckBoxList.js 利用 JQuery 来处理:

扩展了 Array :

Array.prototype.initItem

Array.prototype.hasItem

Array.prototype.addItem

Array.prototype.removeItem

Array.prototype.joinItem

函数responseOnFormClick 检测当前点击是否在弹出的DIV 范围;否则隐藏弹出的DIV  function (e, prefix);

代码语言:javascript
复制
 1 //<!--检测当前点击是否在弹出的DIV 范围;否则隐藏弹出的DIV-->
 2 function responseOnFormClick(e, prefix) {
 3     idPrefix = prefix;
 4     $divObj = $("#" + idPrefix + "_div");
 5     if ($divObj.css("display") == "none") {
 6         return false;
 7     }
 8     var $imgDownObj = $("#" + idPrefix + "_imgDown");
 9     var $imgUpObj = $("#" + idPrefix + "_imgUp");
10     var targetId;
11     if ($.browser.msie) { targetId = e.srcElement.id; }
12     else { targetId = e.target.id; }
13     if (targetId == undefined || targetId.indexOf(idPrefix) < 0) {
14         $divObj.css("display", "none");
15         $imgDownObj.css("display", "inline");
16         $imgUpObj.css("display", "none");
17     }
18     return false;
19 }

函数 toggleDivShowState 显示或者隐藏弹出的DIV

代码语言:javascript
复制
 1 ////显示或者隐藏弹出的DIV
 2 function toggleDivShowState(prefix, splitorString, iCount) {
 3     idPrefix = prefix;
 4     splitor = splitorString;
 5     itemCount = iCount;
 6     vItems = new Array(iCount);
 7     vItems.initItem();
 8     tItems = new Array(iCount);
 9     tItems.initItem();
10     vtItems = new Array(iCount);
11     vtItems.initItem();
12     $hfTextObj = $("#" + idPrefix + "_selectItemValueText");
13     $hfValueObj = $("#" + idPrefix + "_selectItemValue");
14     $divObj = $("#" + idPrefix + "_div");
15     $txtObj = $("#" + idPrefix + "_txtMain");
16     setObjectState(idPrefix + "_div");
17     if ($divObj.css("display") == "inline") {
18         selectDefaultItem(idPrefix + "_selectItemValue", idPrefix);
19     }
20     setObjectState(idPrefix + "_imgDown");
21     setObjectState(idPrefix + "_imgUp");
22 }

函数 selectDefaultItem 弹出DIV 时设置上次选择的值

代码语言:javascript
复制
 1 function selectDefaultItem(hfValueId, prefix) {
 2     $hfValueObj = $("#" + hfValueId);
 3     if (!$hfValueObj.val())
 4     { return; }
 5     var arr = $hfValueObj.val().split(splitor);
 6     if (!arr)
 7     { return; }
 8     vItems.initItem();
 9     tItems.initItem();
10     vtItems.initItem();
11     var subNodes;
12     var firstNode;
13     var lastNode;
14     var nodeValue;
15     var nodeText;
16     var $tdNodes;
17     $divObj = $("#" + prefix + "_div");
18     var $tableNodes = $divObj.children('table');
19     var tableId = $tableNodes.get(0).id;
20     $("#" + tableId + " tr").each(function () {
21         $tdNodes = $(this).children('td');
22         $tdNodes.each(function () {
23             subNodes = this;
24             firstNode = subNodes.children[0];
25             lastNode = subNodes.children[1];
26             nodeValue = firstNode.value;
27             if (nodeValue) {
28                 if (lastNode.innerText)
29                 { nodeText = lastNode.innerText; }
30                 else
31                 { nodeText = lastNode.textContent; }
32                 if (arr.hasItem(nodeValue)) {
33                     if (!vItems.hasItem(nodeValue))
34                     { vItems.addItem(nodeValue); }
35                     if (!tItems.hasItem(nodeText))
36                     { tItems.addItem(nodeText); }
37                     if (!vtItems.hasItem(nodeValue + "|" + nodeText))
38                     { vtItems.addItem(nodeValue + "|" + nodeText); }
39                     if (!tItems.hasItem(nodeText))
40                     { tItems.addItem(nodeText); }
41                     if (!vtItems.hasItem(nodeValue + "|" + nodeText))
42                     { vtItems.addItem(nodeValue + "|" + nodeText); }
43                     firstNode.checked = true;
44                 }
45             }
46         });
47     });
48 
49     $txtObj.val(tItems.joinItem(splitor));
50     $hfTextObj.val(vtItems.joinItem(splitor));
51     $hfValueObj.val(vItems.joinItem(splitor));
52 }

控件支持主流浏览器 IE 7+,FF3.5+,Chrome 9+,Safari 5 等浏览器。但在 IE6中与 与浏览器自身的 select 冲突。

点击下载本例源码

转自:http://www.soaspx.com/dotnet/asp.net/Control/control_20111011_8134.html

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2012-05-03 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档