posts - 615, comments - 10492, trackbacks - 594, articles - 0
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

扩展GridView控件(2) - 复合排序和排序状态提示

Posted on 2007-01-03 18:55 webabcd 阅读(...) 评论(...) 编辑 收藏
GridView既强大又好用。为了让它更强大、更好用,我们来写一个继承自GridView的控件。
[索引页]
[源码下载]


扩展GridView控件(2) - 复合排序和排序状态提示


作者:webabcd


/*正式版的实现 开始*/

介绍
扩展GridView控件:
对多个字段进行复合排序;升序、降序的排序状态提示

使用方法(设置SmartSorting复合属性):
AllowSortTip - 是否启用排序提示
AllowMultiSorting - 是否启用复合排序
SortAscImageUrl - 升序提示图片的URL(不设置则使用默认图片)
SortDescImageUrl - 降序提示图片的URL(不设置则使用默认图片)
SortAscText - 升序提示文本
SortDescText - 降序提示文本


关键代码
using System;
using System.Collections.Generic;
using System.Text;

using System.Web.UI.WebControls;
using System.Web.UI;

namespace YYControls.SmartGridViewFunction
{
    
/// <summary>
    
/// 扩展功能:复合排序和排序状态提示
    
/// </summary>

    public class SmartSortingFunction : ExtendFunction
    
{
        
/// <summary>
        
/// 构造函数
        
/// </summary>

        public SmartSortingFunction()
            : 
base()
        
{

        }


        
/// <summary>
        
/// 构造函数
        
/// </summary>
        
/// <param name="sgv">SmartGridView对象</param>

        public SmartSortingFunction(SmartGridView sgv)
            : 
base(sgv)
        
{

        }


        
/// <summary>
        
/// 扩展功能的实现
        
/// </summary>

        protected override void Execute()
        
{
            
// 开启SmartGridView的排序功能
            
// this._sgv.AllowSorting = true;

            
this._sgv.Sorting += new System.Web.UI.WebControls.GridViewSortEventHandler(_sgv_Sorting);
            
this._sgv.RowDataBoundCell += new SmartGridView.RowDataBoundCellHandler(_sgv_RowDataBoundCell);
        }


        
/// <summary>
        
/// SmartGridView的RowDataBoundCell事件
        
/// </summary>
        
/// <param name="sender"></param>
        
/// <param name="gvtc"></param>

        void _sgv_RowDataBoundCell(object sender, GridViewTableCell gvtc)
        
{
            
if (!String.IsNullOrEmpty(this._sgv.SortExpression) 
                
&& this._sgv.SmartSorting.AllowSortTip
                
&& gvtc.RowType == DataControlRowType.Header)
            
{
                
// 显示排序状态提示
                DisplaySortTip(this._sgv.SortExpression, gvtc.TableCell);
            }

        }


        
/// <summary>
        
/// Sorting事件
        
/// </summary>
        
/// <param name="sender"></param>
        
/// <param name="e"></param>

        void _sgv_Sorting(object sender, System.Web.UI.WebControls.GridViewSortEventArgs e)
        
{
            
// 如果允许复合排序的话,则设置复合排序表达式
            if (this._sgv.SmartSorting.AllowMultiSorting)
            
{
                e.SortExpression 
= GetSortExpression(e);
            }

        }


        
/// <summary>
        
/// 获得复合排序表达式
        
/// </summary>
        
/// <param name="e"></param>
        
/// <returns></returns>

        protected string GetSortExpression(GridViewSortEventArgs e)
        
{
            
string[] sortColumns = null;
            
string sortAttribute = this._sgv.SortExpression;

            
if (!String.IsNullOrEmpty(sortAttribute))
            
{
                sortColumns 
= sortAttribute.Split(',');
            }


            
// 如果原排序表达式有当前排序字段
            if (sortAttribute.IndexOf(e.SortExpression) != -1)
            
{
                
// 更新排序表达式
                sortAttribute = ModifySortExpression(sortColumns, e.SortExpression);
            }

            
else
            
{
                
// 为原排序表达式添加新的排序规则(升序)
                sortAttribute += String.Concat(",", e.SortExpression, " ASC");
            }


            
return sortAttribute.Trim(',');
        }


        
/// <summary>
        
/// 更新排序表达式
        
/// </summary>
        
/// <param name="sortColumns">各个字段的排序表达式数组</param>
        
/// <param name="sortExpression">当前需要排序的字段(该字段在sortColumns数组中)</param>
        
/// <returns></returns>

        protected string ModifySortExpression(string[] sortColumns, string sortExpression)
        
{
            
// 当前需要排序的字段的升序表达式
            string ascSortExpression = String.Concat(sortExpression, " ASC");
            
// 当前需要排序的字段的降序表达式
            string descSortExpression = String.Concat(sortExpression, " DESC");

            
for (int i = 0; i < sortColumns.Length; i++)
            
{
                
// 各个字段的排序表达式数组中,有当前需要排序的字段的升序表达式
                if (ascSortExpression.Equals(sortColumns[i]))
                
{
                    
// 当前排序字段由升序变为降序
                    sortColumns[i] = descSortExpression;
                    
break;
                }

                
// 各个字段的排序表达式数组中,有当前需要排序的字段的降序表达式
                else if (descSortExpression.Equals(sortColumns[i]))
                
{
                    
// 从各个字段的排序表达式数组中,删除当前需要排序的字段
                    Array.Clear(sortColumns, i, 1);
                    
break;
                }

            }


            
return String.Join(",", sortColumns).Replace(",,"",").Trim(',');
        }


        
/// <summary>
        
/// 显示排序状态提示
        
/// </summary>
        
/// <param name="sortExpression">排序表达式</param>
        
/// <param name="tc">Header的TableCell</param>

        protected void DisplaySortTip(string sortExpression, TableCell tc)
        
{
            
string[] sortColumns = sortExpression.Split(',');

            
if (tc.Controls.Count > 0 && tc.Controls[0is LinkButton)
            
{
                
string columnName = ((LinkButton)tc.Controls[0]).CommandArgument;

                
int sortOrderIndex = Array.FindIndex(sortColumns, delegate(string s) return s.IndexOf(columnName) != -1; });

                
// 如果排序表达式中有当前列
                if (sortOrderIndex != -1)
                
{
                    
// 当前列应该是升序还是降序(区分两种情况:复合排序和非复合排序)
                    SortDirection sortDirection = SortDirection.Ascending;
                    
if (this._sgv.SmartSorting.AllowMultiSorting && sortColumns[sortOrderIndex].IndexOf("DESC"!= -1)
                    
{
                        sortDirection 
= SortDirection.Descending;
                    }

                    
else if (!this._sgv.SmartSorting.AllowMultiSorting && this._sgv.SortDirection == SortDirection.Descending)
                    
{
                        sortDirection 
= SortDirection.Descending;
                    }


                    
// 排序状态提示(图片地址)
                    string sortImageUrl = null;
                    
// 排序状态提示(文本)
                    string sortText = null;
                    
if (sortDirection == SortDirection.Ascending)
                    
{
                        sortText 
= this._sgv.SmartSorting.SortAscText;

                        sortImageUrl 
= this._sgv.SmartSorting.SortAscImageUrl;

                        
if (String.IsNullOrEmpty(sortImageUrl))
                        
{
                            sortImageUrl 
= 
                                
this._sgv.Page.ClientScript.GetWebResourceUrl
                                (
                                    
this.GetType(),
                                    
"YYControls.SmartGridView.Resources.Asc.gif"
                                );
                        }

                    }

                    
else
                    
{
                        sortText 
= this._sgv.SmartSorting.SortDescText;

                        sortImageUrl 
= this._sgv.SmartSorting.SortDescImageUrl;

                        
if (String.IsNullOrEmpty(sortImageUrl))
                        
{
                            sortImageUrl 
= 
                                
this._sgv.Page.ClientScript.GetWebResourceUrl
                                (
                                    
this.GetType(),
                                    
"YYControls.SmartGridView.Resources.Desc.gif"
                                );
                        }

                    }


                    
// 添加排序状态提示图片
                    Image imgSortDirection = new Image();
                    imgSortDirection.ImageUrl 
= sortImageUrl;
                    tc.Controls.Add(imgSortDirection);

                    
// 添加排序状态提示文本
                    tc.Controls.Add(new LiteralControl(sortText));

                    
if (this._sgv.SmartSorting.AllowMultiSorting)
                    
{
                        
// 添加排序状态提示序号
                        tc.Controls.Add(new LiteralControl((sortOrderIndex + 1).ToString()));
                    }


                    
不用资源文件,又没有设置排序状态提示时的逻辑(已经注释掉了)

                }
 // if (sortOrderIndex != -1)
            }
 // if (tc.Controls.Count > 0 && tc.Controls[0] is LinkButton)
        }

    }

}


/*正式版的实现 结束*/


/*测试版的实现 开始*/

介绍
在用GridView自带的排序功能排序时,无法直观的知道当前是通过哪个字段排序?是升序还是降序?所以扩展一下,用图片或文字的形式来提示一下当前是根据哪个字段排序,是升序还是降序。


控件开发
1、新建一个继承自GridView的类。
    /// <summary>
    
/// 继承自GridView
    
/// </summary>

    [
    ToolboxData(
@"<{0}:SmartGridView runat='server'></{0}:SmartGridView>"),
    ParseChildren(
true),
    PersistChildren(
false)
    ]
    
public class SmartGridView : GridView
    
{
    }

2、新建一个SortTip实体类,有4个属性,分别是降序提示图片、升序提示图片、降序提示文本和升序提示文本
using System;
using System.Collections.Generic;
using System.Text;

using System.ComponentModel;

namespace YYControls.SmartGridView
{
    
/// <summary>
    
/// 排序提示类
    
/// </summary>

    [TypeConverter(typeof(ExpandableObjectConverter))]
    
public class SortTip
    
{
        
private string _sortDescImage;
        
/// <summary>
        
/// 降序提示图片
        
/// </summary>

        [
        Description(
"降序提示图片"),
        Category(
"扩展"),
        Editor(
"System.Web.UI.Design.UrlEditor"typeof(System.Drawing.Design.UITypeEditor)),
        DefaultValue(
""),
        NotifyParentProperty(
true)
        ]
        
public string SortDescImage
        
{
            
get return _sortDescImage; }
            
set { _sortDescImage = value; }
        }


        
private string _sortAscImage;
        
/// <summary>
        
/// 升序提示图片
        
/// </summary>

        [
        Description(
"升序提示图片"),
        Category(
"扩展"),
        Editor(
"System.Web.UI.Design.UrlEditor"typeof(System.Drawing.Design.UITypeEditor)),
        DefaultValue(
""),
        NotifyParentProperty(
true)
        ]
        
public string SortAscImage
        
{
            
get return _sortAscImage; }
            
set { _sortAscImage = value; }
        }


        
private string _sortDescText;
        
/// <summary>
        
/// 降序提示文本
        
/// </summary>

        [
        Description(
"降序提示文本"),
        Category(
"扩展"),
        DefaultValue(
""),
        NotifyParentProperty(
true)
        ]
        
public string SortDescText
        
{
            
get return _sortDescText; }
            
set { _sortDescText = value; }
        }


        
private string _sortAscText;
        
/// <summary>
        
/// 升序提示文本
        
/// </summary>

        [
        Description(
"升序提示文本"),
        Category(
"扩展"),
        DefaultValue(
""),
        NotifyParentProperty(
true)
        ]
        
public string SortAscText
        
{
            
get return _sortAscText; }
            
set { _sortAscText = value; }
        }


        
/// <summary>
        
/// ToString()
        
/// </summary>
        
/// <returns></returns>

        public override string ToString()
        
{
            
return "SortTip";
        }

    }

}


3、在继承自GridView的那个类中加1个复杂对象属性,这个复杂对象就是第2步创建的那个SortTip
        private SortTip _sortTip;
        
/// <summary>
        
/// 排序提示信息
        
/// </summary>

        [
        Description(
"排序提示信息"),
        Category(
"扩展"),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
        PersistenceMode(PersistenceMode.InnerProperty)
        ]
        
public virtual SortTip SortTip
        
{
            
get
            
{
                
if (_sortTip == null)
                
{
                    _sortTip 
= new SortTip();
                }

                
return _sortTip;
            }

        }

4、重写OnRowDataBound实现给字段标题加上排序状态的功能。主要是根据GridView.SortExpression和GridView.SortDirection来实现这样的功能。
        /// <summary>
        
/// OnRowDataBound
        
/// </summary>
        
/// <param name="e"></param>

        protected override void OnRowDataBound(GridViewRowEventArgs e)
        
{
            
if (e.Row.RowType == DataControlRowType.Header)
            
{
                
// GridViewRow的每个TableCell
                for (int i = 0; i < e.Row.Cells.Count; i++)
                
{
                    
// TableCell里有一个Control并且是LinkButton
                    if (e.Row.Cells[i].Controls.Count == 1 && e.Row.Cells[i].Controls[0is LinkButton)
                    
{
                        
// LinkButton的命令参数等于排序字段
                        if (((LinkButton)e.Row.Cells[i].Controls[0]).CommandArgument == this.SortExpression)
                        
{
                            Image img 
= null;
                            Label lbl 
= null;

                            
// 升序
                            if (this.SortDirection == SortDirection.Ascending)
                            
{
                                
// 升序图片
                                if (!String.IsNullOrEmpty(_sortTip.SortAscImage))
                                
{
                                    img 
= new Image();
                                    img.ImageUrl 
= base.ResolveUrl(_sortTip.SortAscImage);
                                }

                                
// 升序文字
                                if (!String.IsNullOrEmpty(_sortTip.SortAscText))
                                
{
                                    lbl 
= new Label();
                                    lbl.Text 
= _sortTip.SortAscText;
                                }

                            }

                            
// 降序
                            else if (this.SortDirection == SortDirection.Descending)
                            
{
                                
// 降序图片
                                if (!String.IsNullOrEmpty(_sortTip.SortDescImage))
                                
{
                                    img 
= new Image();
                                    img.ImageUrl 
= base.ResolveUrl(_sortTip.SortDescImage);
                                }

                                
// 降序文字
                                if (!String.IsNullOrEmpty(_sortTip.SortDescText))
                                
{
                                    lbl 
= new Label();
                                    lbl.Text 
= _sortTip.SortDescText;
                                }

                            }


                            
// TableCell里加上图片
                            if (img != null)
                            
{
                                e.Row.Cells[i].Controls.Add(img);
                            }

                            
// TableCell里加上文字
                            if (lbl != null)
                            
{
                                e.Row.Cells[i].Controls.Add(lbl);
                            }

                        }

                    }

                }

            }


            
base.OnRowDataBound(e);
        }



控件使用
添加这个控件到工具箱里,然后拖拽到webform上,设置其SortTip下的4个属性即可。SortAscImage是升序提示图片;SortAscText是升序提示文本;SortDescImage是降序提示图片;SortDescText是降序提示文本
ObjData.cs
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

using System.ComponentModel;

/// <summary>
/// OjbData 的摘要说明
/// </summary>

public class OjbData
{
    
public OjbData()
    
{
        
//
        
// TODO: 在此处添加构造函数逻辑
        
//
    }


    [DataObjectMethod(DataObjectMethodType.Select, 
true)]
    
public DataTable Select()
    
{
        DataTable dt 
= new DataTable();
        dt.Columns.Add(
"no"typeof(string));
        dt.Columns.Add(
"name"typeof(string));

        
for (int i = 0; i < 30; i++)
        
{
            DataRow dr 
= dt.NewRow();
            dr[
0= "no" + i.ToString().PadLeft(2'0');
            dr[
1= "name" + i.ToString().PadLeft(2'0');

            dt.Rows.Add(dr);
        }


        
return dt;
    }

}


Default.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    
<title>无标题页</title>
</head>
<body>
    
<form id="form1" runat="server">
        
<div>
            
<yyc:SmartGridView ID="SmartGridView1" runat="server" AutoGenerateColumns="True"
                AllowSorting
="True" DataSourceID="ObjectDataSource1">
                
<Columns>
                    
<asp:ButtonField CommandName="ConfirmTest" Text="确认按钮测试" />
                
</Columns>
                
<SortTip SortAscImage="~/Images/asc.gif" SortDescImage="~/Images/desc.gif" />
            
</yyc:SmartGridView>
            
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server" SelectMethod="Select"
                TypeName
="OjbData"></asp:ObjectDataSource>
        
</div>
  
</form>
</body>
</html>

/*测试版的实现 结束*/


OK
[源码下载]