我正在创建一个扩展WebControl的自定义控件。此Web控件允许使用者在标记中定义列的集合,如下所示:
<Custom:CustomGrid>
<Columns>
<Custom:DataColumn HeaderText="FirstName" />
<Custom:DataColumn HeaderText="LastName" />
</Columns>
并将IEnumerable放在DataSource属性中,并将其呈现给表。 该控件还允许分页。 DataSource中的IEnumerable是完整列表,我一次显示列表的页面。我已经将当前页面,每页行数等保存到viewstate。我还应该将完整列表放在viewstate中吗?也许会话? 这个清单可能会变得有点沉重。也许使用随机密钥保存在会话中,该密钥保存在viewstate中? 这里的最佳做法是什么?
编辑:我认为将IEnumerable中的所有类型都序列化是不对的。那是公平的吗?那么我是否需要将数据源复制到其他数据结构以进行序列化?
编辑2:即使我使用基本控件而不是实现RenderChildControls,我也需要实现CreateChildControls,但我仍然需要在某处保留数据,或者我是否错过了基类?
答案 0 :(得分:2)
实际上,并非所有IEnumerable
实例都可以序列化。
如果查询运行起来很便宜,我不会保留整个数据集,只是再次为不同的页面运行查询或更改排序顺序。
如果您将数据放在viewstate中,您最终会得到大页面。如果您没有很多用户,则可以接受会话状态,但是具有大量用户的大型数据集将无法很好地扩展。如果我将一百万行绑定到您的控件怎么办?或者如果您的控件在转发器中使用并在页面上显示100次会怎么样?
您确定需要保留数据吗?这不是过早的优化吗?
请记住,您的控件是一个UI组件。视图状态应该包含足够的信息以维持UI状态。状态的改变(例如:切换到不同的结果页面)是您的控件应该将责任传递给数据源的东西。
看看好老GridView
。它会显示您提供的内容并记住它。如果你正在使用分页,那么它会引发一个事件,说“用户已经改变了页面;给我第x页数据”。对我来说,这是UI控件的最佳实践。
答案 1 :(得分:0)
为了实现数据绑定控制,最好使用旨在执行此类任务的基类。例如,在ASP.NET中存在CompositeDataboundControl,它可以用作实现自定义数据绑定控件的基类。我可以建议回顾以下Dino Esposito文章: http://msdn.microsoft.com/en-us/library/aa479016.aspx
基本上,如果您创建像ASP.NET gridview这样的控件,那么它就是viewstate中的商店值。更清楚的是,创建了DataStow控件的编号,这些控件在viewstate中保存了指定的值。在回发期间,它会重新创建相同数量的行,并从viewstate恢复值。如果您在不使用viewstate的情况下仅在会话中保存数据源,则需要在每次回发期间将数据重新分配到网格中。因此,如果您创建类似于gridview的Server控件,那么Dino Esposito帖子中描述的方法将非常有用,因为它显示了如何创建类似于ASP.NET Server GridView控件的控件。