2013-01-02 119 views
1

ASP.NET [Horizontal scroll fro GridView] 水平滚动展示了如何水平滚动条添加到我的网的ASP.NET没有寻呼机

的问题是,它也是滚动周围自动生成的寻呼机。

我可以做外部传呼机,但肯定会有更好的解决方案吗?

现在的问题是:是否有一种简单的方法可以让我的GridView在水平滚动而不会使页面滚动。

+0

通过Id或类名查找寻呼机,并使用css隐藏其溢出属性。 – Dev

+0

它很困难,因为GridView呈现在表格上,所以它们一起移动,并且不能在div上放置一些行。你可以做到这一点,以提取寻呼机行,并将其放置在表外的div中,在滚动的外侧。为此,您需要使用jQuery来避免大量额外的代码。 – Aristos

+0

这些都是一些有趣的想法,但没有js/jq/css的实际知识,我还挺卡在这里。 – Nahum

回答

0

erich007给了一个非常有趣的答案,这可能是路要走,但我没有;没有时间来测试它。

以下方法为我工作:

报价:

http://blogs.visoftinc.com/2008/03/19/extending-the-gridview-to-work-with-the-new-datapager-control/

扩展GridView控件将工作与新DataPager控件

通过戴夫·马里尼|发布日期:2008年3月19日 Technorati标签:ASP.NET,C#

最近,我阅读了Scott Mitchell关于.NET Framework 3.5版中包含的新ListView和DataPager控件的文章。这让我很好奇如何适应GridView等其他众所周知的数据绑定控件,以便它们可以与DataPager控件一起使用。在阅读了一些轻量级的内容并且对GridView控件的内容进行了深入的反思之后,我制定了一个游戏计划并准备好了。扩展数据绑定控件以允许与DataPager控件进行通信并不太困难,但它确实假定您已理解数据如何绑定到控件。但是为什么在GridView内置自己的分页控件时这么做呢?那么,一方面,能够将寻呼机与电网分离,可以让我们做一些非常酷的事情。我可以想到的一件事是在左侧栏中使用GridView,并在主窗口中使用分页控件。另外,我们可以有两个传呼机的网格。无论我们使用哪一页来浏览我们的数据,每个人都始终跟踪当前页面。最后,与单独的GridView的模板控件相比,寻呼机的模板控件非常强大。

让我们从数据绑定控件如何与DataPager进行通信开始。 DataPager控件可以连接到任何实现System.Web.Extensions程序集中的IPageableItemContainer接口的控件。这里的接口是什么样子.net反射的礼貌快速射击:

public interface IPageableItemContainer 
{ 
    //Events 
    event EventHandler<PageEventArgs> TotalRowCountAvailable; 
    // Methods 
    void SetPageProperties(int startRowIndex, int maximumRows, bool databind); 
    // Properties 
    int MaximumRows { get; } 
    int StartRowIndex { get; } 
} 

接口的MaximumRows和StartRowIndex性质只是在那里为您的数据绑定控件来确定数据窗口中显示的方式。这有效地定义了您认为是数据“页面”的基础。 SetPageProperties方法在与DataPager的交互中非常重要,因为这是控件中DataPager每次单击任何DataPagerField控件(例如Next或Previous Button)时都会调用的方法。最后,该接口定义了一个名为TotalRowCountAvailable的事件。此事件告诉DataPager有多少记录在绑定到您的控件的数据中。这显然很重要,因为DataPager使用总行数来确定如何显示手动页面按钮,或者是否禁用下一个或上一个按钮,以便您不会访问不存在的页面索引。

因此,让我们开始使用DataPager的钩子扩展GridView。根据GridView思考IPageableItemContainer接口,我们认识到MaximumRows等同于现有的PageSize属性,并且可以从现有的PageSize和PageIndex属性计算出StartRowIndex。我们还通过声明并创建相应的事件调用程序来准备该事件。由于我希望我的新Paging功能成为此网格的默认功能,因此我强制寻呼机在每次页面加载时都隐藏自己。如果你愿意,你可以添加一个切换到这个行为。最后,我们列出SetPageProperties方法,但我们暂时将它留空,因为我们很快会重新访问它。到目前为止,我们的新的GridView看起来是这样的:

public class PageableGridView : GridView, IPageableItemContainer 
{ 
    public PageableGridView() : base() 
    { 
      PagerSettings.Visible = false; 
    } 
    public event EventHandler<PageEventArgs> TotalRowCountAvailable; 
    public int MaximumRows 
    { 
      get{ return this.PageSize; } 
    } 
    public int StartRowIndex 
    { 
      get{ return (this.PageSize * this.PageIndex); } 
    } 
    protected virtual void OnTotalRowCountAvailable(PageEventArgs e) 
    { 
      if (TotalRowCountAvailable != null) 
       TotalRowCountAvailable(this, e); 
    } 
    protected virtual void SetPageProperties(int startRowIndex, int maximumRows, bool dataBind) { } 
} 

好消息是,我们是不是还有一半以上。现在是事情变得更加复杂的地方。我们仍然需要一种方法来根据DataPager说我们需要在用户单击其中一个按钮时显示的内容来设置页面大小和起始行值。这是SetPageProperties方法的作用。这是一个基本的实现,能够完成任务:

保护的虚拟无效SetPageProperties(INT startRowIndex,INT maximumRows,布尔数据绑定) { 如果(数据绑定) { 每页= maximumRows; int newPageIndex =(startRowIndex/PageSize); (PageIndex!= newPageIndex) { OnPageIndexChanging(new GridViewPageEventArgs(newPageIndex)); PageIndex = newPageIndex; OnPageIndexChanged(EventArgs.Empty); } } RequiresDataBinding = databind; } 当DataPager发送网格的分页信息时,网格需要自己设置任何适当的参数以准备绑定到正确的数据窗口。网格已经配备的2个属性是PageSize和PageIndex属性。这些属性可以通过发送到方法的信息来计算,所以我们设置它们。当然,如果页面正在更改,我们可能应该触发OnPageIndexChanging事件。这意味着如果你没有绑定到数据源,你仍然需要确保处理这个事件。最后,如果DataPager处于绑定数据的过程中,我们会指示网格重新绑定。这是一个基本的实现,因此您还需要在此处执行任何数据完整性检查,例如检查以确保新的PageIndex和StartRowIndex值位于有效范围内。

只有一件事可以完成我们的GridView到DataPager的集成。为了让DataPager呈现适当数量的页面按钮,或者让它知道何时禁用寻呼机上的下一页或上一页按钮,它需要知道总共有多少行。这与DataPager本身声明指定的页面大小相结合,可以帮助确定数据源包含的页面数量。问题是,这些信息并不为传呼机所知。然而,GridView已知它,我们需要从那里获取它并将其传递给DataPager。但是,我们什么时候才能确定GridView具有这些数据? GridView控件继承自CompositeDataboundControl。此类型包含CreateChildControls方法的一个特殊变体,该方法还包含一个属性,用于指示控件是绑定到数据还是简单地重新渲染。有点反思表明,GridView使用此方法绑定到其数据源。知道这一点,看起来这是我们要注入触发器的地方,以便引发TotalRowCountAvailable事件。这会变得有点复杂,因为我们需要处理手动绑定到数据源或使用像ObjectDataSource或SqlDataSource这样的数据源控件的情况,这些数据源具有在其中指定的总行数。需要一对夫妇的辅助方法,以确保我们得到正确的值:

//Gets row count from SqlDataSource and the like... 
private int _GetTotalRowsFromDataSourceObject(IEnumerable dataSource) 
{ 
    DataSourceView view = this.GetData(); if (AllowPaging && view.CanPage && view.CanRetrieveTotalRowCount) 
     return base.SelectArguments.TotalRowCount; 
    else 
     return (PageIndex * PageSize) + _GetSourceCount(dataSource); 
} 
//Gets the row count from a manually bound source or from a source in viewstate 
private int _GetSourceCount(IEnumerable dataSource) 
{ 
    ICollection source = dataSource as ICollection; 
    return source != null ? 
     source.Count : 
     (from x in dataSource.OfType<object>() select 1).Sum(); 
} 

的_GetTotalRowsFromDataSourceObject方法从数据源对象检索的记录的总数,如果它是可用的。这取决于几件事情,比如EnablePaging属性是否设置在DataSource控件上以及对象是否已完成查询操作。最糟糕的情况是,我们返回一页数据并完成它。 _GetSourceCount方法用于两个特定的场合。首先,在手动绑定网格的DataSource属性然后调用DataBind()的情况下,如何获取行数。其次,当网格在回传到存储在视图状态中的数据后重新绑定时,这种方法也将证明是有用的。在这两种情况下,我们都使用一些linq来提取数据源中结果数据项的总数(或视图状态下的行)。现在,让我们看看如何使用这些方法来将其结合在一起:

protected override int CreateChildControls(IEnumerable dataSource, bool dataBinding) 
    { 
     int baseResult = base.CreateChildControls(dataSource, dataBinding); 
     if (dataSource != null) 
     { 
      int dataSourceCount = (IsBoundUsingDataSourceID && dataBinding) ? 
       _GetTotalRowsFromDataSource(dataSource) : 
       _GetSourceCount(dataSource); 
      OnTotalRowCountAvailable(new PageEventArgs(StartRowIndex, MaximumRows, dataSourceCount)); 
     } 
     return baseResult; 
    } 

基站控制的CreateChildControls方法首先被调用,因为网格使用它实际做数据绑定。如果没有要绑定的数据,就没有理由通知寻呼机,所以我们检查以确保我们有数据,然后通过上述过程确定数据源中的行数。最后,我们使用派生数据来引发事件,然后返回原始结果,以免影响可能依赖它的任何其他操作。我们现在有了一个可以与新的DataPager控件耦合的GridView。这里的标记,我们会用一个页面上使用这些控件一起样本:

<asp:DataPager ID="DataPager1" runat="server" PageSize="2" PagedControlID="grid2"> 
    <Fields> 
     <asp:NextPreviousPagerField /> 
    </Fields> 
</asp:DataPager> 

<custom:pageablegridview id="grid2" runat="server" autogeneratecolumns="true" allowpaging="true" 
     onpageindexchanging="grid2_PageIndexChanging" /> 

请注意,我没有指定GridView控件的PageSize属性,因为在DataPager的PageSize属性将在控制这个值。为了确保这一点,我们可以在网格上隐藏PageSize属性,但现在就足够了。所以这就是它的全部。对于绑定到数据的新创建的服务器控件,使这些入侵允许您的控件使用DataPager非常简单。对于像GridView这样的现有控件,只需要知道绑定是如何发生的,然后将功能注入到某个知道需要的值存在的地方。

2

另一种解决方案更简单:

  1. 创建一个空表,并给它一个ID。在我的情况下,customPager
  2. 给你默认的GridView寻呼机一个css风格你只需要一个名称没有css编码
  3. 包括jQuery的在您的aspx(头部分)。
  4. 你看,两行脚本的下面......那些移动的默认寻呼,你把customPager

这是我能产生最简单的外...希望它帮助。 ..

<table id="customPager"> 

    </table> 
    <hr /> 
     <div id="dvGridView" style="height: 200px;overflow:scroll;"> 
     <asp:GridView ID="GridView1" runat="server" AllowPaging="True" PageSize="5"> 
      <PagerSettings Position="Top" /> 
      <PagerStyle CssClass="pagerStyle" /> 
     </asp:GridView> 
    </div> 
    <script> 
     $('#customPager').html($('.pagerStyle').html()); 
     $('.pagerStyle').html(''); 
    </script> 
+0

你的把戏看起来不错,但不幸的是,我会提供一个解决方案,并在几分钟前实现 – Nahum

+0

我很高兴你解决了你的问题,谢谢你的观点... – erichste