根据上面一篇随笔所介绍的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来解决问题。