11: asp:ContentPlaceHolder> 12: form> 13: body> 14: html>
项目中的那个instnwnd.sql是取自Microsoft提供的SQL Server 2000 Sample Databases里的Northwind数据库的脚本.使用脚本建立Northwind数据库. 并将连接字符串加入web.config.
3. 建立数据访问类NorthwindData.cs. 后面我们将使用ObjectDataSource组件来为SPGridView提供数据.
1: using System; 2: using System.Data; 3: using System.Data.SqlClient; 4: using System.Configuration; 5: 6: namespace SPGridView_Demo 7: { 8: public class NorthwindData 9: { 10: private static string connectionString = null; 11: 12: public NorthwindData() 13: { 14: if(string.IsNullOrEmpty(connectionString)) 15: { 16: connectionString = ConfigurationManager.ConnectionStrings["Northwind"].ConnectionString; 17: } 18: } 19: 20: public int GetProductCount() 21: { 22: int count = 0; 23: string commandText = "SELECT COUNT(ProductId) FROM dbo.Products"; 24: SqlConnection connection = new SqlConnection(connectionString); 25: SqlCommand command = new SqlCommand(commandText, connection); 26: connection.Open(); 27: count = Convert.ToInt32(command.ExecuteScalar()); 28: connection.Close(); 29: return count; 30: } 31: 32: public DataTable GetProductList(string sortExpression) 33: { 34: DataTable dt = new DataTable(); 35: string commandText = "SELECT ProductId, ProductName, p.CategoryId, p.UnitPrice, p.Discontinued, c.CategoryName FROM dbo.Products p INNER JOIN dbo.Categories c ON p.CategoryId = c.CategoryId ORDER BY {SORT}"; 36: 37: if(sortExpression == null || sortExpression.Trim() == string.Empty) 38: { 39: sortExpression = "ProductId"; 40: } 41: 42: commandText = commandText.Replace("{SORT}", sortExpression); 43: SqlConnection connection = new SqlConnection(connectionString); 44: SqlDataAdapter adapter = new SqlDataAdapter(commandText, connection); 45: connection.Open(); 46: adapter.Fill(dt); 47: connection.Close(); 48: return dt; 49: } 50: 51: public DataTable GetProductList(int startRowIndex, int maximumRows, string sortExpression) 52: { 53: DataTable dt = new DataTable(); 54: string commandText = "SELECT * FROM (SELECT ProductId, ProductName, p.CategoryId, UnitPrice, p.Discontinued, c.CategoryName, ROW_NUMBER() OVER (ORDER BY {SORT}) AS RowNumber FROM dbo.Products p INNER JOIN dbo.Categories c ON p.CategoryId = c.CategoryId) a WHERE RowNumber BETWEEN @StartRowIndex + 1 AND @StartRowIndex + @MaximumRows"; 55: 56: if(sortExpression == null || sortExpression.Trim() == string.Empty) 57: { 58: sortExpression = "ProductId"; 59: } 60: 61: commandText = commandText.Replace("{SORT}", sortExpression); 62: SqlConnection connection = new SqlConnection(connectionString); 63: SqlDataAdapter adapter = new SqlDataAdapter(commandText, connection); 64: adapter.SelectCommand.Parameters.Add(new SqlParameter("@StartRowIndex", startRowIndex)); 65: adapter.SelectCommand.Parameters.Add(new SqlParameter("@MaximumRows", maximumRows)); 66: connection.Open(); 67: adapter.Fill(dt); 68: connection.Close(); 69: return dt; 70: } 71: } 72: }
4. 创建 SPGVP1.aspx
我们先试着绑些数据给SPGridView, 再发布到MOSS里看看效果吧.
代码:
1: 2: 3: 4: 5: asp:Content> 6: 7: asp:Content> 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: asp:Label>itemtemplate> 19: asp:TemplateField> 20: Columns> 21: cc1:SPGridView> 22: asp:ObjectDataSource> 23: asp:Content>
效果:
然后我们给Product Name列加入项菜单吧, 我们计划给它加入2个菜单项, 1个是链接型View Deltail, 另1个是回发型Order Now. 觉得不过瘾再加个带!号的Order Now, 用于区别Unit Price高于$40的产品好了.
我们把Product Name列那行代码
改成
基中MenuTemplateId属性指定了一个菜单模板(MenuTemplate), 菜单模板也是一个SharePoint控件类.将下面的代码加到SPGridView代码之外.
cc1:MenuTemplate>
注意: ID为mitView的菜单项模板使用了ClientOnClickNavigateUrl属性来指定此菜单项的连接, 它类似与HyperLinkField的DataNavigateUrlFormatString属性, 但是变量标识是%Alias%, 而不是{index}或列名. 这里的数据别名(Alias)是在调用此菜单模板的SPMenuField的TokenNameAndValueFields指定的, 格式为 "别名1=列名1,别名2=列名2,...".
特别注意: 我们使用了PNAME 代表ProductName的数据, 如果数据里包含单/双引号等字符, 会导致菜单项失灵. 因为最终控件生成的HTML代码将是 location.href='XXXXX' 或 ''__doPostBack('YYYYYY')". 哈! 像JS注入吧~.
然后我们在SPGridVIew的OnRowDataBound事件中写些判断代码来控制不同情况下菜单模板的显示. 我们不打算让用户订购Discontinued的产品, 并在订购菜单项中使用!号图标提示该产品单价超过了$40.
protected void SPGridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if(e.Row.RowType == DataControlRowType.DataRow)
{
Microsoft.SharePoint.WebControls.Menu menu = e.Row.Cells[1].Controls[0] as Microsoft.SharePoint.WebControls.Menu;
if(menu != null)
{
bool discontinued = Convert.ToBoolean(DataBinder.Eval(e.Row.DataItem, "Discontinued"));
decimal unitPrice = Convert.ToDecimal(DataBinder.Eval(e.Row.DataItem, "UnitPrice"));
if(discontinued)
{
menu.HiddenMenuItems.Add(this.mitOrder);
menu.HiddenMenuItems.Add(this.mitOrderWarn);
}
if(unitPrice >= 40m)
{
menu.HiddenMenuItems.Add(this.mitOrder);
}
else
{
menu.HiddenMenuItems.Add(this.mitOrderWarn);
}
}
}
}
让我们来看看现在实现了的效果.
我们还需要给Order Now菜单项添加回发行为.
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
this.mitOrder.ClientOnClickUsingPostBackEventFromControl(this.SPGridView1, "Order:%PID%");
this.mitOrderWarn.ClientOnClickUsingPostBackEventFromControl(this.SPGridView1, "Order:%PID%");
}这样我们的Order Now菜单项的点击行为会变成 __doPostBack('ctl00$PlaceHolderMain$SPGridView1','Order:22') 的样子. 现在我们加入代码来响应这些回发操作.
private void Order(string pid)
{
Response.Write(pid + " is ordered.");
}
protected override void RaisePostBackEvent(IPostBackEventHandler sourceControl, string eventArgument)
{
base.RaisePostBackEvent(sourceControl, eventArgument);
if(eventArgument == null || eventArgument.Trim() == string.Empty)
{
return;
}
if(eventArgument.Contains(":"))
{
int posIndex = eventArgument.IndexOf(":");
string commandName = eventArgument.Substring(0, posIndex);
string argument = eventArgument.Remove(0, posIndex + 1);
switch(commandName)
{
case "Order":
this.Order(argument);
break;
}
this.SPGridView1.DataBind();
}
}
Isn't it amazing?
完整代码: