我正在使用带有SPGridView的ObjectDataSource(基于GridView的SharePoint控件),并查看日志,SelectMethod被调用九次 - 这是它真正需要的8倍。
我想知道是否有人确切地知道ObjectDataSource对象在什么条件下会调用Select方法,或者要检查的大量事项列表/关于优化它的任何建议?它是DataBound所以这意味着它全部归结为SPGridView?
我知道selectcount方法会调用它一次(as per this SO answer),但我真的不明白为什么它需要多次调用select方法。我在错误的步骤绑定了吗?在错误的步骤初始化?我也启用了分页,排序和过滤......任何提示都会很棒:)
编辑:我在事件中添加了一些日志代码,看起来GridView上的DataBinding事件被多次命中,这是否意味着内部SPGridView多次调用DataBind()?我调用的唯一DataBind()是用户控件中的Render事件,它只被引发一次。记录跟踪:
ODS_Selecting
ODS_ObjCreating
ODS_Selecting
Gridview_DataBinding
ODS_Selecting
ODS_ObjCreating
ODS_Selecting
Gridview_DataBinding
GridView_RowDataBound
...
GridView_RowDataBound
ODS_Selecting
ODS_ObjCreating
ODS_Selecting
Gridview_DataBinding
GridView_RowDataBound
...
GridView_RowDataBound
ODS_Selecting
ODS_ObjCreating
ODS_Selecting
Gridview_DataBinding
GridView_RowDataBound
...
GridView_RowDataBound
ODS_Selecting
ODS_ObjCreating
ODS_Selecting
Gridview_DataBinding
GridView_RowDataBound
...
GridView_RowDataBound
ODS_Selecting
ODS_ObjCreating
ODS_Selecting
Gridview_DataBinding
GridView_RowDataBound
...
GridView_RowDataBound
ODS_Selecting
ODS_ObjCreating
ODS_Selecting
Gridview_DataBinding
GridView_RowDataBound
...
GridView_RowDataBound
ODS_Selecting
ODS_ObjCreating
ODS_Selecting
Gridview_DataBinding
GridView_RowDataBound
...
GridView_RowDataBound
ODS_Selecting
ODS_ObjCreating
ODS_Selecting
Gridview_DataBinding
GridView_RowDataBound
....
GridView_RowDataBound
ODS_Selecting
ODS_ObjCreating
ODS_Selecting
Gridview_DataBinding
GridView_RowDataBound
....
GridView_RowDataBound
而且,这里有很多代码!
的.ascx:
<SharePoint:SPGridView ID="appGridView" DataSourceID="appODS" AutoGenerateColumns="false"
AllowPaging="true" PageSize="10" AllowSorting="true"
AllowFiltering="true" FilterDataFields=",,,,TimeElapsed,,," FilteredDataSourcePropertyName="FilterExpression" FilteredDataSourcePropertyFormat="{1} = '{0}'"
runat="server" />
<wc:ObjectDataSource ID="appODS" runat="server" />
<SharePoint:SPGridViewPager ID="appGridViewPager" runat="server" GridViewId="appGridView" />
.ascx.cs:
public partial class MyUserControl:UserControl {
//http://www.reversealchemy.net/blog/2009/05/01/building-a-spgridview-control-part-1-introducing-the-spgridview/
//http://www.reversealchemy.net/2009/05/24/building-a-spgridview-control-part-2-filtering/
protected override void OnInit(EventArgs e)
{
appODS.EnablePaging = true;
appODS.SelectMethod = "GetMyDataTable";
appODS.SelectCountMethod = "GetMyDataTableCount";
appODS.StartRowIndexParameterName = "rowStart";
appODS.MaximumRowsParameterName = "rowCount";
appODS.SelectParameters.Add(new Parameter { Name = "myParam", DefaultValue = "test" });
appODS.TypeName = this.GetType().AssemblyQualifiedName;
appODS.ObjectCreating += new ObjectDataSourceObjectEventHandler(appODS_ObjectCreating);
appGridView.RowDataBound += new GridViewRowEventHandler(appGridView_RowDataBound);
appODS.Filtering += new ObjectDataSourceFilteringEventHandler(appODS_Filtering);
appGridView.Sorting += new GridViewSortEventHandler(appGridView_Sorting);
}
//https://stackoverflow.com/questions/1351578/spgridview-data-and-correct-method-of-ensuring-data-is-safe
protected override void OnPreRender(EventArgs e)
{
if (!string.IsNullOrEmpty(appODS.FilterExpression))
{
appODS.FilterExpression = string.Format(
appGridView.FilteredDataSourcePropertyFormat,
appGridView.FilterFieldValue.Replace("'", "''"),
appGridView.FilterFieldName
);
}
base.OnPreRender(e);
}
private void appODS_ObjectCreating(object sender, ObjectDataSourceEventArgs e)
{
e.ObjectInstance = this;
}
protected sealed override void Render(HtmlTextWriter writer)
{
GenerateColumns();
appGridView.DataBind();
base.Render(writer);
}
public DataTable GetMyDataTable(string myParam, int rowStart, int rowCount)
{
DataTable dt = new DataTable();
dt.Columns.Add("ID", typeof(Int32));
// more columns here
dt.Columns.Add("TestColumn", typeof(decimal));
List<Stuff> things = svc.GetStuff();
foreach (Stuff thing in things)
{
dt.Rows.Add(
thing.Blah, thing.Blah2);
}
return dt;
}
public int GetMyDataTableCount(string myParam)
{
return 10003; //faked out for now
}
private void GenerateColumns()
{
BoundField column = new BoundField();
column.DataField = "ID";
column.SortExpression = "ID";
column.HeaderText = "ID";
appGridView.Columns.Add(column);
//more
column = new BoundField();
column.DataField = "TestColumn";
column.SortExpression = "TestColumn";
column.HeaderText = "TestColumn";
appGridView.Columns.Add(column);
}
////filtering
protected sealed override void LoadViewState(object savedState)
{
base.LoadViewState(savedState);
if (Context.Request.Form["__EVENTARGUMENT"] != null &&
Context.Request.Form["__EVENTARGUMENT"].EndsWith("__ClearFilter__"))
{
// Clear FilterExpression
ViewState.Remove("FilterExpression");
}
}
private void appODS_Filtering(object sender, ObjectDataSourceFilteringEventArgs e)
{
ViewState["FilterExpression"] = ((ObjectDataSourceView)sender).FilterExpression;
}
private void appGridView_Sorting(object sender, GridViewSortEventArgs e)
{
if (ViewState["FilterExpression"] != null)
{
appODS.FilterExpression = (string)ViewState["FilterExpression"];
}
}
private void appGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (sender == null || e.Row.RowType != DataControlRowType.Header)
{
return;
}
SPGridView grid = sender as SPGridView;
if (String.IsNullOrEmpty(grid.FilterFieldName))
{
return;
}
// Show icon on filtered column
for (int i = 0; i < grid.Columns.Count; i++)
{
DataControlField field = grid.Columns[i];
if (field.SortExpression == grid.FilterFieldName)
{
Image filterIcon = new Image();
filterIcon.ImageUrl = "/_layouts/images/filter.gif";
filterIcon.Style[HtmlTextWriterStyle.MarginLeft] = "2px";
// If we simply add the image to the header cell it will
// be placed in front of the title, which is not how it
// looks in standard SharePoint. We fix this by the code
// below.
Literal headerText = new Literal();
headerText.Text = field.HeaderText;
PlaceHolder panel = new PlaceHolder();
panel.Controls.Add(headerText);
panel.Controls.Add(filterIcon);
e.Row.Cells[i].Controls[0].Controls.Add(panel);
break;
}
}
}
}
答案 0 :(得分:0)
我最终通过甩掉反射器并进行更多挖掘来解决这个问题 - 事实证明我甚至不需要在Render方法中调用.DataBind(),因为SPGridView继承自BaseDataBoundControl,确保在必要时调用DataBind - 根据我在MSDN上的理解,它被称为OnPreRender。
事实证明,通过在Render事件中生成列(appGridView.Columns.Add(column);),每次我修改appGridView时,DataBind()方法最终再次被调用 - 所以Render事件是设置gridview Columns为时已晚,因为在那个阶段它已经完成所有已经完成的工作,并且每次添加新的时候都必须“重新绑定”以获取数据。
这是一个巨大的性能问题,如果你在how to set up a SPGridView with ObjectDataSource上关注其他不错的例子,你应该注意这一点。