也算是自己刚毕业时候的作品吧,当时在一家创业公司工作,考虑给公司建立一个公司的控件库,于是也学习过一段时间的控件设计,当时领我入门的是《道不远人》那本控件开发书,觉得谭振宁写的还是相当不错的,推荐一下:)。那么就开始分享我设计的一些控件,并且告诉一些基本的设计思路。
具体实现了这些控件:
CheckTextBox: 可以对于输入TextBox的字符做出判断
HighSlideHyperLink: 点击HyperLink可以弹出相关Div层或者Img图象
ContextMenu: 上下文菜单特效
Menu: 菜单特效
EnablePageDataList: 具有分页功能的DataList
EnablePageRepeater: 具有分页功能的Repeater
GroupDropDownList: 具有分组选项功能的DropDownList
GroupListBox: 具有分组选项功能的ListBox
SearchCloud:Tag云图,可以根据关键词的搜索数量,进行排列
1. CheckTextBox
效果图:
该控件继承自TextBox控件:
[DefaultProperty("Text")]
[ToolboxData("<{0}:CheckTextBox runat=server>")]
public class CheckTextBox : TextBox
{
...
}
控件的属性代码:
private TextType _inputType;
[Description(@"文本框输入的类型:
String------任意文本,
Upper---------大写,
Lower---------小写,
Number--------任意数字,
FormatNumber--格式化指定的小数,
Date----------日期,
ChineseLanguage-中文,
IP------------IP地址,
Phone---------固定电话
")
]
public TextType InputType
{
get
{
return _inputType;
}
set
{
if((value < TextType.String) || (value > TextType.Phone))
{
throw new ArgumentOutOfRangeException("无效属性值");
}
_inputType = value;
}
}
Description属性将在设计窗口属性中显示出描述:
通过AddAttributesToRender方法实现脚本的注册:
protected override void AddAttributesToRender(HtmlTextWriter writer)
{
...
}
其中InputType包括几种方式以及一些事件发生的脚本:
public static class TextScript
{
public static string ChineseLanguage = @"/^[\u4E00-\u9FA5]*$/";
public static string Lower = @"/^[a-z]*$/";
public static string Number = @"/^[0-9]*$/";
public static string Phone = @"/^\d{1,4}([-\/](\d{1,8}?)?)?$/";
public static string IP = @"/^\d{1,3}([.\/](\d{1,3}([.\/](\d{1,3}([.\/](\d{1,3}([.\/](\d{1,3}([.\/](\d{1,3}?)?)?)?)?)?)?)?)?)?)?$/";
public static string Upper = @"/^[A-Z]*$/";
public static string OnKeyPress = @"return regInput(this, {0},String.fromCharCode(event.keyCode))";
public static string OnPaste = @"return regInput(this,{0},window.clipboardData.getData('Text'))";
public static string OnDrop = @"return regInput(this,{0},event.dataTransfer.getData('Text'))";
public static string OnFocusCloseInput = "this.style.imeMode='disabled'";
}
2. HighSlideHyperLink
效果图:
看到类的头部:
[assembly: WebResource("Conovosoft.Web.UI.WebControls.highslide.css", "text/css")]
[assembly: WebResource("Conovosoft.Web.UI.WebControls.highslide.js", "text/javascript")]
[assembly: WebResource("Conovosoft.Web.UI.WebControls.highslide-html.js", "text/javascript")]
这里控件需要引用一些JS以及CSS的资源文件,highslide作为第三方的JS脚本,为了实现图片放大的效果。
在OnPreRender方法中注册脚本文件:
protected override void OnPreRender(EventArgs e)
{
RegisterClientCSSResource("Conovosoft.Web.UI.WebControls.highslide.css");
Page.ClientScript.RegisterClientScriptResource(this.GetType(),
"Conovosoft.Web.UI.WebControls.highslide.js");
Page.ClientScript.RegisterClientScriptResource(this.GetType(),
"Conovosoft.Web.UI.WebControls.highslide-html.js");
if (!Page.ClientScript.IsStartupScriptRegistered("baseTextScript"))
{
if (this.ControlType == InputType.Div)
{
if (!string.IsNullOrEmpty(this.DivID))
{
this.Page.ClientScript.RegisterStartupScript(this.GetType(), "baseTextScript", @"", false);
}
}
if (this.ControlType == InputType.Img)
{
if (!string.IsNullOrEmpty(this.CaptionID))
{
this.Page.ClientScript.RegisterStartupScript(this.GetType(), "baseTextScript", @"", false);
}
}
}
base.OnPreRender(e);
}
调用代码:
ID="HighSlideHyperLink2" runat="server">
<img border="0" src="images/thumb.jpg" />
</cc1:HighSlideHyperLink>
3. EnablePageRepeater
效果图:
using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI.WebControls;
using System.ComponentModel;
using System.Collections;
namespace Conovosoft.Web.UI.WebControls
{
public class EnablePageRepeater : Repeater
{
private static readonly object EventPageIndexChanged = new object();
PagedDataSource pagedDataSource;
[DefaultValue(false), Category("Paging")]
public virtual bool AllowPaging
{
get
{
object obj2 = this.ViewState["AllowPaging"];
if (obj2 != null)
{
return (bool)obj2;
}
return false;
}
set
{
this.ViewState["AllowPaging"] = value;
}
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
Browsable(false)]
public virtual int VirtualItemCount
{
get
{
object obj2 = this.ViewState["VirtualItemCount"];
if (obj2 != null)
{
return (int)obj2;
}
return 0;
}
set
{
if (value < 0)
{
throw new ArgumentOutOfRangeException("value");
}
this.ViewState["VirtualItemCount"] = value;
}
}
[DefaultValue(10), Category("Paging")]
public virtual int PageSize
{
get
{
object obj2 = this.ViewState["PageSize"];
if (obj2 != null)
{
return (int)obj2;
}
return 10;
}
set
{
if (value < 1)
{
throw new ArgumentOutOfRangeException("value");
}
this.ViewState["PageSize"] = value;
}
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
Browsable(false)]
public int PageCount
{
get
{
if (this.pagedDataSource != null)
{
return this.pagedDataSource.PageCount;
}
object obj2 = this.ViewState["PageCount"];
if (obj2 == null)
{
return 0;
}
return (int)obj2;
}
}
[Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public int CurrentPageIndex
{
get
{
object obj2 = this.ViewState["CurrentPageIndex"];
if (obj2 != null)
{
return (int)obj2;
}
return 0;
}
set
{
if (value < 0)
{
throw new ArgumentOutOfRangeException("value");
}
this.ViewState["CurrentPageIndex"] = value;
OnPageIndexChanged(new DataGridPageChangedEventArgs(this, value));
}
}
protected virtual void OnPageIndexChanged(DataGridPageChangedEventArgs e)
{
DataGridPageChangedEventHandler handler = (DataGridPageChangedEventHandler)Events[EventPageIndexChanged];
if (handler != null)
handler(this, e);
}
[Category("Action")]
public event DataGridPageChangedEventHandler PageIndexChanged
{
add
{
base.Events.AddHandler(EventPageIndexChanged, value);
}
remove
{
base.Events.RemoveHandler(EventPageIndexChanged, value);
}
}
protected override System.Collections.IEnumerable GetData()
{
IEnumerable dataSource = base.GetData();
if (AllowPaging && dataSource != null)
{
pagedDataSource = new PagedDataSource();
ICollection collection = dataSource as ICollection;
if (collection != null)
{
pagedDataSource.VirtualCount = collection.Count;
VirtualItemCount = pagedDataSource.VirtualCount;
}
else if (dataSource is IListSource)
{
pagedDataSource.VirtualCount = (dataSource as IListSource).GetList().Count;
VirtualItemCount = pagedDataSource.VirtualCount;
}
else if (VirtualItemCount > 0)
{
pagedDataSource.VirtualCount = VirtualItemCount;
}
else
{
pagedDataSource = null;
return dataSource;
}
pagedDataSource.DataSource = dataSource;
pagedDataSource.CurrentPageIndex = CurrentPageIndex;
pagedDataSource.PageSize = PageSize;
pagedDataSource.AllowPaging = true;
pagedDataSource.AllowCustomPaging = false;
ViewState["PageCount"] = pagedDataSource.PageCount;
return pagedDataSource;
}
return dataSource;
}
}
}
实现了带分页的Repeater控件。同理,也可以实现带分页的DataList。
4. GroupDropDownList
效果图:
控件代码:
using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI.WebControls;
using System.Web.UI;
using System.ComponentModel;
using System.Web;
namespace Conovosoft.Web.UI.WebControls
{
[ToolboxData("<{0}:GroupDropDownList runat=server>")]
public class GroupDropDownList : DropDownList
{
public GroupDropDownList()
{
}
///
/// 用于添加GroupDropDownList的分组项的ListItem的Value值
///
[
Browsable(true),
Description("用于添加GroupDropDownList的分组项的ListItem的Value值"),
Category("扩展")
]
public virtual string OptionGroupValue
{
get
{
string s = (string)ViewState["OptionGroupValue"];
return (s == null) ? "optgroup" : s;
}
set
{
ViewState["OptionGroupValue"] = value;
}
}
protected override void RenderContents(HtmlTextWriter writer)
{
OptionAndGroupRenderContents(writer);
}
///
/// 呈现Option或者OptionGroup
///
///
private void OptionAndGroupRenderContents(HtmlTextWriter writer)
{
// 是否需要呈现OptionGroup的EndTag
bool writerEndTag = false;
foreach (ListItem li in this.Items)
{
// 如果没有optgroup属性则呈现Option
if (li.Value != this.OptionGroupValue)
{
// 呈现Option
RenderListItem(li, writer);
}
// 如果有optgroup属性则呈现OptionGroup
else
{
if (writerEndTag)
// 呈现OptionGroup的EndTag
OptionGroupEndTag(writer);
else
writerEndTag = true;
// 呈现OptionGroup的BeginTag
OptionGroupBeginTag(li, writer);
}
}
if (writerEndTag)
// 呈现OptionGroup的EndTag
OptionGroupEndTag(writer);
}
///
/// 呈现Option
///
///
///
private void RenderListItem(ListItem li, HtmlTextWriter writer)
{
writer.WriteBeginTag("option");
// 写入Option的Value
writer.WriteAttribute("value", li.Value);
if (li.Selected)
{
// 如果该Option被选中则写入selected
writer.WriteAttribute("selected", "selected");
}
foreach (string key in li.Attributes.Keys)
{
// 写入Option的其它属性
writer.WriteAttribute(key, li.Attributes[key]);
}
writer.Write(HtmlTextWriter.TagRightChar);
// 写入Option的Text
HttpUtility.HtmlEncode(li.Text, writer);
writer.WriteEndTag("option");
writer.WriteLine();
}
///
/// 呈现OptionGroup的BeginTag
///
///
///
private void OptionGroupBeginTag(ListItem li, HtmlTextWriter writer)
{
writer.WriteBeginTag("optgroup");
// 写入OptionGroup的label
writer.WriteAttribute("label", li.Text);
foreach (string key in li.Attributes.Keys)
{
// 写入OptionGroup的其它属性
writer.WriteAttribute(key, li.Attributes[key]);
}
writer.Write(HtmlTextWriter.TagRightChar);
writer.WriteLine();
}
///
/// 呈现OptionGroup的EndTag
///
///
private void OptionGroupEndTag(HtmlTextWriter writer)
{
writer.WriteEndTag("optgroup");
writer.WriteLine();
}
}
}
注意到RenderContents方法调用了OptionAndGroupRenderContents,通过该方法的逻辑实现Option以及OptionGroup的呈现。
调用代码:
<cc1:GroupDropDownList ID="GroupDropDownList1" runat="server">
</cc1:GroupDropDownList>
后台绑定数据代码:
private void BindGroupDropDownList()
{
//当ListItem的Value值为optgroup时,默认为分组选项
ListItem li = new ListItem("研发中心", "optgroup");
GroupDropDownList1.Items.Add(li);
li = new ListItem("张三", "1");
GroupDropDownList1.Items.Add(li);
li = new ListItem("李四", "2");
GroupDropDownList1.Items.Add(li);
li = new ListItem("销售中心", "optgroup");
GroupDropDownList1.Items.Add(li);
li = new ListItem("王五", "3");
GroupDropDownList1.Items.Add(li);
li = new ListItem("李平", "4");
GroupDropDownList1.Items.Add(li);
}
protected void Button1_Click(object sender, EventArgs e)
{
Page.ClientScript.RegisterClientScriptBlock(Page.GetType(),"Message", string.Format("alert('Text:{0},Value:{1}')", this.GroupDropDownList1.SelectedItem.Text, this.GroupDropDownList1.SelectedValue), true);
}
同样GroupListBox实现代码和GroupDropDownList.cs类似。
5. SearchCloud标签云
效果图:
控件代码:
using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
using System.Data;
using System.Collections;
using System.Text.RegularExpressions;
namespace Conovosoft.Web.UI.WebControls
{
[ToolboxData("<{0}:SearchCloud runat=server>")]
public class SearchCloud : WebControl
{
#region "属性"
#region "Appearance"
[Bindable(true), Category("Appearance"), Localizable(true)]
public int MinFontSize
{
get
{
string s = (string)ViewState["MinFontSize"];
if (String.IsNullOrEmpty(s))
return 10;
else
{
int result = 10;
int.TryParse(s, out result);
return result;
}
}
set
{
ViewState["MinFontSize"] = value;
}
}
[Bindable(true), Category("Appearance"), Localizable(true)]
public int MaxFontSize
{
get
{
string s = (string)ViewState["MaxFontSize"];
if (String.IsNullOrEmpty(s))
return 22;
else
{
int result = 22;
int.TryParse(s, out result);
return result;
}
}
set
{
ViewState["MaxFontSize"] = value;
}
}
[Bindable(true), Category("Appearance"), Localizable(true)]
public string FontUint
{
get
{
string s = (string)ViewState["FontUint"];
if (String.IsNullOrEmpty(s))
return "pt";
else
return s;
}
set
{
switch (value)
{
case "pt":
case "em":
case "%":
case "px":
ViewState["FontUnit"] = value; break;
default:
ViewState["FontUnit"] = "px"; break;
}
}
}
[Bindable(true), Category("Appearance"), Localizable(true)]
public string MaxColor
{
get
{
string s = (string)ViewState["MaxColor"];
if (String.IsNullOrEmpty(s))
return "#00f";
else
return s;
}
set
{
ViewState["MaxColor"] = value;
}
}
[Bindable(true), Category("Appearance"), Localizable(true)]
public string MinColor
{
get
{
string s = (string)ViewState["MinColor"];
if (String.IsNullOrEmpty(s))
return "#000";
else
return s;
}
set
{
ViewState["MinColor"] = value;
}
}
#endregion
#region "Data"
[Bindable(true), Category("Data"), DefaultValue("")]
public DataSet DataSource
{
get
{
return (DataSet)ViewState["DataSource"];
}
set
{
ViewState["DataSource"] = value;
}
}
[Bindable(true), Category("Data"), DefaultValue(""), Localizable(true)]
public string DataIDField
{
get
{
return (string)ViewState["DataIDField"];
}
set
{
ViewState["DataIDField"] = value;
}
}
[Bindable(true), Category("Data"), DefaultValue(""), Localizable(true)]
public string DataKeywordField
{
get
{
return (string)ViewState["DataKeywordField"];
}
set
{
ViewState["DataKeywordField"] = value;
}
}
[Bindable(true), Category("Data"), DefaultValue(""), Localizable(true)]
public string DataURLField
{
get
{
return (string)ViewState["DataURLField"];
}
set
{
ViewState["DataURLField"] = value;
}
}
[Bindable(true), Category("Data"), DefaultValue(""), Localizable(true)]
public string DataCountField
{
get
{
return (string)ViewState["DataCountField"];
}
set
{
ViewState["DataCountField"] = value;
}
}
[Bindable(true), Category("Data"), Localizable(true)]
public string KeywordTitleFormat
{
get
{
string s = (string)ViewState["KeywordTitleFormat"];
if (String.IsNullOrEmpty(s))
{
return "%k occured %c times";
}
else
{
return (string)ViewState["KeywordTitleFormat"];
}
}
set
{
ViewState["KeywordTitleFormat"] = value;
}
}
[Bindable(true), Category("Data"), Localizable(true)]
public string KeywordURLFormat
{
get
{
return (string)ViewState["KeywordURLFormat"];
}
set
{
ViewState["KeywordURLFormat"] = value;
}
}
[Bindable(true), Category("Data"), DefaultValue(""), Localizable(true)]
public string SortBy
{
get
{
return (string)ViewState["SortBy"];
}
set
{
ViewState["SortBy"] = value;
}
}
#endregion
[Bindable(false), Category("Debug"), DefaultValue(false), Localizable(true)]
public Boolean Debug
{
get
{
if (ViewState["Debug"] != null)
{
return (Boolean)ViewState["Debug"];
}
else
{
return false;
}
}
set
{
ViewState["Debug"] = value;
}
}
#region Private Properties
private Hashtable arrAttributes;
private string CloudHTML
{
get
{
string s = (string)ViewState["CloudHTML"];
if (String.IsNullOrEmpty(s))
{
return string.Empty;
}
return s;
}
set
{
ViewState["CloudHTML"] = value;
}
}
private Hashtable KeyAttributes
{
get
{
return arrAttributes;
}
set
{
arrAttributes = value;
}
}
#endregion
#endregion
protected override void Render(HtmlTextWriter writer)
{
if (!String.IsNullOrEmpty(CloudHTML))
{
writer.WriteBeginTag("div");
if (!String.IsNullOrEmpty(CssClass))
{
writer.WriteAttribute("class", CssClass);
}
writer.Write(HtmlTextWriter.TagRightChar);
writer.Write(CloudHTML);
writer.WriteEndTag("div");
}
else
{
writer.Write("这儿没有产生HTML,一个未操作错误发生.");
}
}
protected override void OnLoad(EventArgs e)
{
if (DataSource == null)
{
CloudHTML = "请指定DataSet";
return;
}
if (DataIDField == string.Empty)
{
CloudHTML = "请指定一个ID数据段";
return;
}
if (DataKeywordField == string.Empty)
{
CloudHTML = "请指定一个关键词数据段";
return;
}
if (DataCountField == string.Empty)
{
CloudHTML = "请指定一个关键词数量数据段";
return;
}
if (!Regex.IsMatch(MinColor, "^#([a-f]|[A-F]|[0-9]){3}(([a-f]|[A-F]|[0-9]){3})?$"))
{
CloudHTML = "最小颜色必须为十六进制编码并且必须为如: #000 or #ff99cc";
return;
}
if (!Regex.IsMatch(MaxColor, "^#([a-f]|[A-F]|[0-9]){3}(([a-f]|[A-F]|[0-9]){3})?$"))
{
CloudHTML = "最小颜色必须为十六进制编码并且必须为如: #000 or #ff99cc";
return;
}
try
{
StringBuilder sb = new StringBuilder();
DataView dv = new DataView(DataSource.Tables[0]);
//DataRowView row;
dv.Sort = string.Format("{0} DESC", DataCountField);
int count = dv.Count;
if (count == 0)
{
CloudHTML = "没有任何值产生云";
return;
}
int MaxQty = int.Parse(dv[0].Row[DataCountField].ToString());
int MinQty = int.Parse(dv[dv.Count - 1].Row[DataCountField].ToString());
int Spread = MaxQty - MinQty;
if (Spread == 0)
Spread = 1;
int FontSpread = MaxFontSize - MinFontSize;
if (FontSpread == 0)
FontSpread = 1;
double FontStep = (double)(FontSpread) / Spread;
if (!string.IsNullOrEmpty(SortBy))
{
dv.Sort = SortBy;
}
else
{
dv.Sort = string.Format("{0} ASC", DataKeywordField);
}
foreach (DataRowView row in dv)
{
int sKeyID = int.Parse(row.Row[DataIDField].ToString());
string sKeyWord = row.Row[DataKeywordField].ToString();
int sKeyCount = int.Parse(row.Row[DataCountField].ToString());
string sKeyURL;
string ColorRGB;
double Weight = MinFontSize + ((sKeyCount - MinQty) * FontStep);
int FontDiff = MaxFontSize - MinFontSize;
double ColorWeight = Math.Round(99 * (Weight - MinFontSize) / (FontDiff) + 1);
if (MinColor == MaxColor)
{
ColorRGB = MinColor;
}
else
{
ColorRGB = Colorize(MinColor, MaxColor, ColorWeight);
}
if (String.IsNullOrEmpty(DataURLField))
{
if (!String.IsNullOrEmpty(KeywordURLFormat))
{
sKeyURL = ReplaceKeyValues(KeywordURLFormat, sKeyID, sKeyWord, "", sKeyCount);
}
else
{
sKeyURL = "#";
}
}
else
{
sKeyURL = row[DataURLField].ToString();
}
sb.Append(string.Format("{3} ",
sKeyURL,
Math.Round(Weight),
ReplaceKeyValues(KeywordTitleFormat, sKeyID, sKeyWord, sKeyURL, sKeyCount),
HttpContext.Current.Server.HtmlEncode(sKeyWord),
ColorRGB,
FontUint,
GenerateAttributes(sKeyWord, sKeyID, sKeyURL, sKeyCount)));
}
CloudHTML = sb.ToString();
}
catch (Exception ex)
{
if (!Debug)
{
CloudHTML = "错误产生";
}
else
{
throw ex;
}
}
finally
{
base.OnLoad(e);
}
}
public void AddAttribute(string value, string text)
{
if (KeyAttributes == null)
{
KeyAttributes = new Hashtable();
}
KeyAttributes.Add(value, text);
}
private string GenerateAttributes(string k, int id, string u, int c)
{
if (KeyAttributes == null)
{
return string.Empty;
}
StringBuilder s = new StringBuilder();
ICollection keys = KeyAttributes.Keys;
foreach (object key in keys)
{
s.Append(string.Format(" {0}=\"{1}\"", key, ReplaceKeyValues(KeyAttributes[key].ToString(), id, k, u, c)));
}
return s.ToString();
}
private string ReplaceKeyValues(string txt, int id, string k, string u, int c)
{
k = k.Replace("'", "'");
txt = txt.Replace("%i", id.ToString());
txt = txt.Replace("%k", HttpContext.Current.Server.HtmlEncode(k));
txt = txt.Replace("%u", u);
txt = txt.Replace("%c", c.ToString());
return txt;
}
private string Colorize(string minc, string maxc, double w)
{
w = w / 100;
string rs, gs, bs;
string r, g, b;
int minr, ming, minb, maxr, maxg, maxb;
if (minc.Length == 4)
{
rs = minc.Substring(1, 1);
gs = minc.Substring(2, 1);
bs = minc.Substring(3, 1);
minc = "#" + rs + rs + gs + gs + bs + bs;
}
if (maxc.Length == 4)
{
rs = maxc.Substring(1, 1);
gs = maxc.Substring(2, 1);
bs = maxc.Substring(3, 1);
maxc = "#" + rs + rs + gs + gs + bs + bs;
}
minr = Convert.ToInt32(minc.Substring(1, 2), 16);
ming = Convert.ToInt32(minc.Substring(3, 2), 16);
minb = Convert.ToInt32(minc.Substring(5, 2), 16);
maxr = Convert.ToInt32(maxc.Substring(1, 2), 16);
maxg = Convert.ToInt32(maxc.Substring(3, 2), 16);
maxb = Convert.ToInt32(maxc.Substring(5, 2), 16);
r = Convert.ToString(int.Parse(Math.Round(((maxr - minr) * w) + minr).ToString()), 16);
g = Convert.ToString(int.Parse(Math.Round(((maxg - ming) * w) + ming).ToString()), 16);
b = Convert.ToString(int.Parse(Math.Round(((maxb - minb) * w) + minb).ToString()), 16);
if (r.Length == 1)
r = "0" + r;
if (g.Length == 1)
g = "0" + g;
if (b.Length == 1)
b = "0" + b;
string color;
color = "#" + r + g + b;
return color;
}
}
}
调用代码:
<cc1:SearchCloud ID="SearchCloud1" runat="server" />
后台绑定数据代码:
protected void Page_Load(object sender, EventArgs e)
{
SqlConnection sqlcn = new SqlConnection(@"server=.\SQL2000;uid=sa;pwd=sa;database=Northwind;");
DataSet ds = new DataSet();
string sql = "select b.keyword_id,b.keyword_value,b.keyword_count from Products a, ";
sql += "(select top 10 [Products].ProductID as keyword_id, ProductName as keyword_value, ";
sql += "count([Order Details].ProductID) as keyword_count ";
sql += "from [Order Details],[Products] ";
sql += "where [Order Details].ProductID = [Products].ProductID ";
sql += "group by [Products].ProductID,ProductName order by keyword_count desc) as b ";
sql += "where a.ProductID = b.keyword_id ";
sql += "order by newid()";
SqlDataAdapter da = new SqlDataAdapter(sql, sqlcn);
da.Fill(ds);
SearchCloud1.DataIDField = "keyword_id";
SearchCloud1.DataKeywordField = "keyword_value";
SearchCloud1.DataCountField = "keyword_count";
SearchCloud1.DataSource = ds;
}
这样就实现了类似博客系统中的标签云。
最后附上我的源代码:WebControl.UI.rar,希望能够给大家带来些ASP.NET服务器控件开发上的帮助!