根据上面一篇随笔所介绍的PC购买流程的项目,在项目中,需要有一个生成订单的功能,能够使得Admin很方便的在获得批准的申请中选取一些来生成订单,要求界面操作简单明了,大概的效果图如下:
点击checkbox,自动计算当前订单的总价值,点击按钮,生成订单。
有此想到了用SPGridView这个现成的控件来完成,以前也用过这个控件,其实和GridView没什么大区别。这里就简单介绍一下了:
首先Create 一个WebPart
在CreateChildControls()中可以设置SPGridView 的数据源和属性,添加Field等等。
但是CheckBox这一列,必须自己自定义一个模板类来生成,下面是我们自定义的CheckBox模板类,它实现了ITemplate接口:
代码
class CheckBoxTemplateField:ITemplate
{
string id;
public EventHandler OnCheck = null;
public CheckBoxTemplateField(string chbId, EventHandler checkEvent)
{
id = chbId;
OnCheck = checkEvent;
}
public void InstantiateIn(System.Web.UI.Control container)
{
CheckBox chb = new CheckBox();
chb.AutoPostBack = true;
chb.ID = id;
chb.CheckedChanged += OnCheck;
container.Controls.Add(chb);
}
}
这样就可以在SPGridView中调用这个模板类,并且为Oncheck事件提供处理方法:
代码
protected override void CreateChildControls()
{
if (!_error)
{
try
{
SPList sourceList = SPContext.Current.Web.Lists["Purchase Request"];
dataSource = new SPDataSource();
this.Controls.Add(dataSource);
dataSource.List = sourceList;
gridView = new SPGridView();
gridView.AutoGenerateColumns = false;
TemplateField chbField = new TemplateField();
chbField.HeaderText = "";
EventHandler onCheck = new EventHandler(OnCheck);
chbField.ItemTemplate = new CheckBoxTemplateField("chb", onCheck);
gridView.Columns.Add(chbField);
当我们提供了所以的Field绑定后,需要指定一列为Group列,我们这里指定了"Team"列:
代码
SPBoundField createdField = CreateNewBoundField("Created", "Created", 0);
gridView.Columns.Add(createdField);
SPBoundField applicantField = CreateNewBoundField("Created By", "Created By", 0);
gridView.Columns.Add(applicantField);
SPBoundField mtField = CreateNewBoundField("Machine Type", "Machine Type", 0);
gridView.Columns.Add(mtField);
SPBoundField compField = CreateNewBoundField("Component Type", "Component Type", 0);
gridView.Columns.Add(compField);
SPBoundField purNumField = CreateNewBoundField("Purchase Number", "Purchase Number", 0);
gridView.Columns.Add(purNumField);
SPBoundField purReasonField = CreateNewBoundField("Purchase Reason", "Purchase Reason", 0);
gridView.Columns.Add(purReasonField);
SPBoundField mgrAppField = CreateNewBoundField("Manager Approval", "Manager Approval", 0);
gridView.Columns.Add(mgrAppField);
SPBoundField drtAppField = CreateNewBoundField("Director Approval", "Director Approval", 0);
gridView.Columns.Add(drtAppField);
SPBoundField priceField = CreateNewBoundField("Total Price", "Total Price", 0);
gridView.Columns.Add(priceField);
gridView.AllowGrouping = true;
gridView.AllowGroupCollapse = true;
gridView.GroupField = "Team";
gridView.GroupFieldDisplayName = "Team";
但是"Team"这个Field在数据源的List中是Lookup类型的,如果不作处理,那么显示的结果将会是Team:23;#SharePoint Test,即 连lookupid也显示出来了,这里我们需要在数据绑定的时候作处理,为此我们添加了gridView.RowDataBound += new GridViewRowEventHandler(gridView_RowDataBound)这个事件,gridView_RowDataBound的代码如下:
代码
void gridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
if ((sender as SPGridView).AllowGrouping)
{
SPGridViewRow gridViewRow = e.Row as SPGridViewRow;
if (gridViewRow != null && gridViewRow.HeaderText != null)
{
gridViewRow.HeaderText = "Team : " + new SPFieldLookupValue(DataBinder.GetPropertyValue(e.Row.DataItem, (sender as SPGridView).GroupField).ToString()).LookupValue;
}
}
}
}
这样,确保我们在SPGridView中做Groupby时,显示的只是LookupValue,而非LookupId;#LookUpValue的形式。
另外我们可以通过设置SPGridView的DataKeyNames为各行保存一些我们可能需要的信息,例如
gridView.DataKeyNames = new string[] { "ID", "Team", "Created By", "Total Price", "Machine Type", "Component Type", "Purchase Number", "Shipped Order" };
如下就可以使用这些数据:
gridView.DataKeys[row.RowIndex].Values["Machine Type"].ToString();
我们用SPGridView作为WebPart开发的时候还遇到了一个问题,就是一访问SharePoint的Session,页面就报异常。但是在代码中,并为出现异常,检查了Web.config文件,发现HttpModule中也加了Session Module,<Page>节点中也Enable了Session, 至今未能找出原因,后来不得已,用了Context.Cache来代替,希望各位看官,有知道原因的,还请不吝赐教。谢谢拉~
SPGridView使用不复杂,关键还在于理清楚项目中的业务逻辑,选择合适的Solution来解决问题。