0

我正在使用带有 SPGridView(基于 GridView 的 SharePoint 控件)的 ObjectDataSource,并查看日志,SelectMethod 被调用了 9 次 - 这比它真正需要的要多 8 倍。

我想知道是否有人确切地知道 ObjectDataSource 对象在什么条件下会调用 Select 方法,或者要检查的一大堆事情/关于优化它的任何建议?它是 DataBound 那么这是否意味着它完全取决于 SPGridView?

我知道 selectcountmethod 调用它一次(根据这个 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:

公共部分类 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;
            }
        }
    }
}
4

1 回答 1

0

我最终通过抽出反射器并进行更多挖掘来解决它 - 结果我什至不需要在 Render 方法中调用 .DataBind() ,因为 SPGridView 继承自BaseDataBoundControl,这确保在必要时调用 DataBind - 根据我在 MSDN 上的理解,它被称为 OnPreRender。

事实证明,通过在 Render 事件(appGridView.Columns.Add(column);)中生成列,每次我修改 appGridView 时,DataBind() 方法都会再次被调用 - 所以 Render 事件为时已晚设置gridview Columns,因为到那个阶段它期望一切都已经完成并且每次我添加一个新的时它都必须“重新绑定”才能获取数据。

这是一个巨大的性能问题,如果您遵循此处关于如何使用 ObjectDataSource 设置 SPGridView的其他不错的示例,您应该注意这一点。

于 2012-09-07T02:15:04.840 回答