2010-07-01 33 views
7

我有一个中继器,显示各种股票的财务数据和价格。如何在回发之后坚持来自转发器的数据?

在这个页面上,我还有一个“导出”按钮,需要将屏幕上的数据〜转换为用户的CSV格式。

的问题是,在我的数据绑定我的“股票”实体名单:

List<Stock> stocks = GetStocks() 
rptStockList.DataSource = stocks; 
rptStockList.DataBind(); 

的数据不会保留在回发。

此外,此页上的数据不断通过UpdatePanel和Timer控件更新(每次重新绑定数据)。每30秒钟,中继控制器中各种股票的价格变化。

现在,我有一个链接按钮,它在代码隐藏方面有一个点击事件方法,它应该在屏幕上为用户导出〜数据。我需要抓住最后一个数据库股票列表的当前值到中继器。我不能简单地从数据库中获取最新值,因为这些值在上次刷新之间的时间内会发生变化。

protected void lbtnExportStocks_Click(object sender, EventArgs e) 
{ 
    // No longer have the stock data used in the repeater control 
    ExportStocksToExcel(); 
} 

我知道,ASP.NET不会持续在后回中继器的数据源,但我需要仍然能够要么重新构建股票的实体名单,所以我可以把他们的CSV或者我需要以某种方式坚持下去。

我不想在性能方面做任何过于沉重的事情,因为在一周中的某些日子里,这个应用程序可能会有一些沉重的用法。

这种情况的适当解决方案是什么?我是否应该遍历Repeater的“Items”集合并重建股票实体?

+1

我认为你需要发布一些关于'ExportStocksToExcel()'的具体信息,因为转发器不应该丢失绑定到它的数据(假设你没有禁用控件或页面上的viewstate),因为viewstate 。但是,如果这是您的预期(或至少以任何合理的方式),则无法从中继器读取数据源中的数据。 – 2010-07-01 18:58:32

+0

@Chris Marisic,因此,根据我上面写的内容,您将如何亲自从中继器获取数据以输出CSV? – Darwin 2010-07-01 19:02:09

+0

@Chris Marisic,截至目前,所有ExportStocksToExcel()都会设置正确的标题和内容类型,然后我将写出一份有关CSV数据的响应。但是,我很难弄清楚如何将数据恢复出来。 – Darwin 2010-07-01 19:03:04

回答

0

这听起来像你的Page_Load方法,你正在做一些绑定到你的中继器。出于您的目的,这是不好的,正如您所看到的,它将在每次回发时不执行您的数据。你能确保你的Page_Load事情是这样的吗? :

Page_Load(...){ 
    if (! Page.IsPostBack){ 
    //first time page loads do this block 

    //stuff 
    //databinding stuff 
    } 
} 
+1

这就是我现在拥有的东西。这是如何帮助我调用导出链接按钮时,数据不会持久的事实? – Darwin 2010-07-01 18:36:36

+0

@达尔文数据可能会持续存在。例如。如果中继器包含用户可设置的文本框,列表框或复选框,则除非您调用'DataBind',否则这些值* ARE *在回发时保留。所以你的数据*可能*已经在'ViewState'中。你可以通过一个runat =“server”按钮进行检查,该按钮除了导致回发之外什么也不做。如果你的数据*被*保留,它应该在点击那个按钮后仍然存在。 – 2010-09-06 10:40:56

1

您可以将stocks存储在Viewstate或Session中吗?例如

List<Stock> stocks = GetStocks() 
rptStockList.DataSource = stocks; 
rptStockList.DataBind(); 

ViewState.Remove("stocks"); 
ViewState.Add("stocks", stocks); 

private void ExportStocksToExcel 
{ 
    List<Stock> persistedStocks; 

    persistedStocks = (List<Stock>)Page.ViewState["stocks"]; 
    ... 
} 

会话状态,实际上可能是更好的选择,用于存储Stocks因为这将不会在页面传输到客户端(与“创意编辑”,可能意味着一切准备) - 这可能是非常重要的在这样的应用程序中。 (是的,你可以加密Viewstate,但要注意那些高峰时间,这可能是你不想要的开销。)

0

我会带Phil的答案并序列化整个数据集,或者创建一些标准对象传递给GetStocks()来指定要获取的数据。然后序列化并将标准对象存储在ViewState中,因此当用户单击“导出”时,可以拉取标准并检索相同的数据。

[Serializable] 
public class StockCriteria 
{ 
    public DateTime DateFrom { get; set; } 
    public DateTime DateTo { get; set; } 
    public string[] Symbols { get; set; } 
} 

然后GetStocks()具有StockCriteria作为参数并基于它的查询。

+0

我想,您可能想要通过一个时间点,否则股票的价格可能会在DateFrom和DateTo之间发生变化...... – PhilPursglove 2010-07-05 15:50:00

1

一个简单的方法是将值呈现为输入控件(而不是<span>或单纯的<td>元素) - 当用户发布时,浏览器将输入值发送回服务器。

例如:

<ItemTemplate> 
    Symbol: <input type="text" readonly="readonly" name="Symbol" value="<%# Container.DataItem("Symbol") %> /> 
    Quote: <input type="text" readonly="readonly" name="Quote" value="<%# Container.DataItem("Quote") %> /> 
</ItemTemplate> 

客户端发送一个名为“符号”在一个阵列(命名,同样的输入值“报价”),每个输入值,你可以在你的访问代码隐藏这样的:

protected void lbtnExportStocks_Click(object sender, EventArgs e) { 

    // They come out as comma-delimited strings 
    string[] symbols = Request.Form["Symbol"].Split(','); 
    string[] quotes = Request.Form["Quote"].Split(','); 

    // ... continue exporting stocks to Excel 
} 

当然,在底部,这种技术基本上是写任何客户端发送您的Excel文件,所以你可能想保护或限制某种方式输入。这可能涉及对用户进行身份验证和/或限制您的方法将导出的数据量。如果这是你的环境中的一个严重问题,或者你不能太在意,请考虑序列化用户会话中的原始数据。

同样,如果您有意地传输大量数据,您应该考虑使用其他方法出于性能原因。您可以使用会话来代替,或者传输一个小密钥,您可以使用该密钥来重建用于构建中继器的数据(例如,如果中继器绑定到查询的结果,而该查询的结果并未根据其输入发生更改,那么您可以在调用之间序列化输入)。