2010-11-29 3 views
2

Примечание: Этот вопрос был полностью изменен сейчас, когда у меня есть более простой пример.ListView + ObjectDataSource SelectMethod вызывается дважды, когда EnableViewState = "false"

Я установил образец страницы, который имеет только ListView и ObjectDataSource. При первой странице страницы (!IsPostBack) мой метод GetList вызывается один раз. После подкачки (IsPostBack) метод GetList вызывается дважды - первый раз со старыми значениями поискового вызова и второй раз с новыми значениями.

Если я установил EnableViewState="true" на ListView, то метод GetList вызывается только один раз. Мне кажется, что ListView хочет «начальное состояние», которое оно либо получает от ViewState, либо путем повторного запуска метода.

Есть ли способ отключить ViewState на ListView, а также не допустить, чтобы SelectMethod был вызван дважды?

ASPX страница:

<asp:ListView ID="TestListView" runat="server" DataSourceID="ODS" EnableViewState="false"> 
     <LayoutTemplate> 
      <asp:PlaceHolder ID="itemPlaceHolder" runat="server" /> 

      <asp:DataPager ID="TestPager" runat="server" PageSize="10"> 
       <Fields> 
        <asp:NumericPagerField /> 
       </Fields> 
      </asp:DataPager> 
     </LayoutTemplate> 
     <ItemTemplate> 
      <div><%# Eval("Title") %></div> 
     </ItemTemplate> 
    </asp:ListView> 

    <asp:ObjectDataSource ID="ODS" runat="server" SelectMethod="GetList" SelectCountMethod="GetListCount" 
     TypeName="Website.Test" EnablePaging="true" /> 

ASPX кода позади:

namespace Website 
{ 
    public partial class Test : System.Web.UI.Page 
    { 
     protected void Page_Load(object sender, EventArgs e) 
     { 

     } 

     public IList<DataItem> GetList(int maximumRows, int startRowIndex) 
     { 
      return GetListEnumerable().Skip(startRowIndex).Take(maximumRows).ToList(); 
     } 

     public IEnumerable<DataItem> GetListEnumerable() 
     { 
      for (int i = 0; i < 100; i++) 
      { 
       yield return new DataItem { Title = i.ToString() }; 
      } 
     } 

     public int GetListCount() 
     { 
      return 100; 
     } 
    } 

    public class DataItem 
    { 
     public string Title { get; set; } 
    } 
} 

ответ

2

Либо включите ODS кэширование.

<asp:ObjectDataSource ID="ODS" ... EnableCaching="true" /> 

Таким образом, GetList будет вызываться только тогда, когда необходимы новые данные. Почтовые обратные ссылки на страницы, на которые уже были получены данные, будут использовать кешированную версию и не вызвать GetList.

Или переместите свой DataPager из ListView и установите свойство PagedControlID.

+0

Я думал кэширование, но в моем случае есть бесконечные возможности параметров, поэтому я хотел бы, чтобы продолжительность кэша быть очень мала (скажем, 10 секунд вершины). Если пользовательские страницы после 10 секунд, это будет еще двойной запрос, который немного замедляет страницу. Включение режима ViewState было бы лучше. Перенос DataPager из ListView не помог - он все еще удваивается. Мне интересно, могу ли я прямо или косвенно (через Reflection) установить `BaseDataBoundControl.RequiresDataBinding`. – 2010-12-01 16:08:29

+0

Я попытался установить `RequiresDataBinding` в false через Reflection и это предотвращает двойной запрос. Однако это первый запрос (до пейджинга), поэтому я не могу его использовать. Наверное, сейчас я оставлю ViewState. – 2010-12-01 16:17:34

+0

Я не думал о параметрах. Я не знаю, как кэширование реализовано, когда дело доходит до этого. Тем не менее, перемещение пейджера из списка привело к хитрости для меня. Думаю, это не надежное решение. RequiresDataBinding получает избыток в нескольких местах. Если позволит время, вы можете попытаться создать свой собственный элемент управления из ListView и обработать как CreateChildren, так и RequiresDataBinding. Тогда всегда есть ViewState ... :) – Ruslan 2010-12-02 21:07:33

0

На самом деле вы должны использовать событие OnSelecting.

Что происходит, что ObjectDataSource вызывает метод SelectMethod дважды

  1. Первый раз, когда он получает данные.
  2. В следующий раз он получает счет.

Так что я думаю, что вы необходимо реализовать OnSelecting событие

<asp:ObjectDataSource ID="ODS" runat="server" SelectMethod="GetList" SelectCountMethod="GetListCount" 
    OnSelecting="ods_Selecting"> 
    TypeName="Website.Test" EnablePaging="true" /> 

, а затем отменить событие, когда ObjectDataSource пытается вызвать метод подсчета.

protected void ods_Selecting(object sender, 
       ObjectDataSourceSelectingEventArgs e) 
{ 
     if (e.ExecutingSelectCount) 
     { 
      //Cancel the event 
      return; 
     } 
} 

Вы можете посмотреть на полное осуществление, как указаны в ссылке ниже http://www.unboxedsolutions.com/sean/archive/2005/12/28/818.aspx

Надеется, что это помогает.

0

У меня была схожая проблема, когда она работала по-разному в зависимости от браузера. IE в одну сторону и все другие браузеры в одну сторону. Возможно, это не та же проблема, что и у вас.

Я решил это так:

 protected void DropDownDataBound(object sender, EventArgs e) 
    { 
     // Issue with IE - Disable ViewState for IE browsers otherwhise the dropdown will render empty. 
     DropDownList DDL = (DropDownList)sender; 
     if (Request.Browser.Browser.Equals("IE", StringComparison.CurrentCultureIgnoreCase)) 
      DDL.ViewStateMode = System.Web.UI.ViewStateMode.Disabled; 
     else 
      DDL.ViewStateMode = System.Web.UI.ViewStateMode.Inherit;   
    } 
Смежные вопросы