【问题标题】:looping through results using C# and tableadapter使用 C# 和 tableadapter 循环遍历结果
【发布时间】:2015-08-20 18:20:40
【问题描述】:

目前,当我按下上一个按钮时,它只会将结果返回到我的文本框。我希望它循环遍历结果。所以第一次点击按钮时,它会显示第一条记录,循环播放。

protected void btnPrevious_Click1(object sender, EventArgs e)
{
    DAL.TicketsDataSetTableAdapters.TicketDetailsTableAdapter eobj = new DAL.TicketsDataSetTableAdapters.TicketDetailsTableAdapter();
    DataTable dt = new DataTable();
    dt = eobj.GetTicketUpdates(txtSupportRef.Text);

    txtNextStep.Text = eobj.GetTicketData(txtSupportRef.Text).Rows[0]["NextStep"].ToString();
}

我想知道如何返回我的所有记录,然后根据每次点击循环遍历它们?

这个想法是,当您选择一张票时,它会将最新的详细信息加载到表单中。但后来我的意图是有一个上一个和下一个按钮,这样我就可以循环浏览一张票的各种更新......

【问题讨论】:

  • 所以基本上 Click 1 会显示第一条记录。点击 2 会显示第二个等等?
  • 是的,现场......
  • 您的数据是如何排序的,是否所有内容都在一张表中?还是将详细信息存储在第二个表中并链接到工单?我可以看到的第一件事是您需要加载所有数据并将其放入某种类型的控件(GridView?)并使用主从关系。在 Click 事件中使用它的方式是在每次点击时不必要地重新加载数据。如果你有一个组合框来选择你的票号,那么下面有一个细节控件,你可以翻阅每个项目(如果你是这样排序的话,按日期顺序)。

标签: c# asp.net .net loops tableadapter


【解决方案1】:

您需要跟踪点击次数。这样的东西就是你想要的。

protected void btnPrevious_Click1(object sender, EventArgs e)
{
    if (Session["ClickCount"] == null)
        Session["ClickCount"] = 0;

    int ClickCount = Convert.ToInt32(Session["ClickCount"]) + 1;
    Session["ClickCount"] = ClickCount;

    DAL.TicketsDataSetTableAdapters.TicketDetailsTableAdapter eobj = new DAL.TicketsDataSetTableAdapters.TicketDetailsTableAdapter();
    DataTable dt = new DataTable();
    eobj.GetTicketUpdates(txtSupportRef.Text);

    txtNextStep.Text = eobj.GetTicketData(txtSupportRef.Text).Rows[ClickCount - 1]["NextStep"].ToString();
}

【讨论】:

  • 嗨@Jason Geiger,这对我来说不太适用。我不认为会话是做到这一点的好方法。这个想法是,当您选择一张票时,它会将最新的详细信息加载到表单中。但是我的意图是有一个上一个和下一个按钮,以便我可以循环浏览票证的各种更新......你看看我是否然后从下拉列表中选择另一个票证参考,你建议的会话变量方法将继续计数,我会得到一个There is no row at position <NUMBER> 错误。您认为返回各个更新数据的最佳方式是什么?
【解决方案2】:

所以我知道您想要一系列记录集合,其中包含当前选择的记录集合以及前进到下一个记录集合或上一个记录集合的可能性。

循环:

  • 如果当前选择的记录集合是第一个并且选择了上一个,那么您需要最后一个记录集合
  • 如果当前选择的记录集合是最后一个并且选择了 Next,那么您需要第一个记录集合

这个怎么样:

class CollectionLooper<IEnumerable<T>>()
{
    private List<IEnumerable<T>> collections = null;
    private int selectedIndex = 0;

    public CollectionLooper(IEnumerable<IEnumerable<T> collections)
    {
        if (collections == null) throw new ArgumentNullException("collections");
        this.collections = collections.ToList().AsReadOnly;
        // postcondition: this.collection refers to a list of IEnumerable<T>
        // that might be empty
        // if the list is not empty, then this.selectedIndex refers to
        // the first element of the list
    }

    // if the list is empty: return null: no sequence selected
    // if not empty: return the selected sequence
    public IEnumerable<T> SelectedCollection {get{return this.collection.Any() ?
       return this.collections(this.selectedIndex) : null;} }

    // if the list is empty: does nothing but return null, there is no next collection
    // otherwise: select the next collection in the sequence and return it
    public IEnumerable<T> NextCollection { { get
    {
        if (this.collection.Any())
        {
            this.selectedIndex = (++this.selectedIndex) % this.collections.Count();
            return this.SelectedCollection;
        }
        else return null;
    }

    // if the list is empty: does nothing but return null,
    // there is no previous collection
    // otherwise: select the previous collection in the sequenc and return it
    public IEnumerable<T> PreviousCollection { { get
    {
        if (this.collection.Any())
        {
            this.selectedIndex = (--this.selectedIndex) % this.collections.Count();
            return this.SelectedCollection;
        }
        else return null;
    }
}

考虑向添加集合添加函数,以使对集合集的更改成为可能。

考虑使类 IEnumerable> 使 Linq 的使用成为可能。

能够从列表中删除项目是不明智的,因为这会使当前选择的元素无效。

最后一点:拥有一个包含两个值的属性 TransactionRef 有点危险:如果在“|”之前或之后有空格怎么办?最好将 TransactionRef 设为具有属性编号 ("20150824") 和 Guid ("Guid1") 的类。

【讨论】:

    【解决方案3】:

    更改数据库选择方法以根据当前值获取下一个和上一个票证更新。 期望 txtNextStep.Tag 包含对当前票证更新代码的引用可能如下所示:

        protected void btnNext_Click1(object sender, EventArgs e)
        {
            DAL.TicketsDataSetTableAdapters.TicketDetailsTableAdapter eobj = new DAL.TicketsDataSetTableAdapters.TicketDetailsTableAdapter();
            DataTable dt = new DataTable();
            if (txtNextStep.Tag == null)//Pick first update.
                dt = eobj.GetTicketFirstUpdate(txtSupportRef.Text);
            else//Getting next ticket update for the ticket based on current displaying value
                dt = eobj.GetNextTicketUpdate(txtSupportRef.Text, (string)txtNextStep.Tag);
    
            if (dt.Rows.Count != 0)
            {
                txtNextStep.Text = dt.Rows[0]["NextStep"].ToString();
                txtNextStep.Tag = dt.Rows[0]["Id"].ToString();
            }
        }
    

    出于性能考虑,读取多个工单更新 id 可能是有意义的,因此在按下按钮的情况下,将执行按 id 读取,而不是搜索下一个或上一个工单更新。

    【讨论】:

    • 是的,没有标签,所以它可以是页面上的另一个隐藏字段,也可以使用 ViewState 来存储值
    • 为什么我会有一个隐藏字段。 txtNextStep.Text 是一个可见的字段......它包含文本。
    • txtSupportRef 将是页面的唯一 ID。
    • 我可能没有隐藏字段,可以显示给用户。这取决于你
    • 什么意思:dt = eobj.GetNextTicketUpdate(txtSupportRef.Text, (string)txtNextStep.Tag);
    【解决方案4】:

    就我个人而言,我会有一个跟踪用户当前“点击”的计数,如下所示:

    protected void btnPrevious_Click1(object sender, EventArgs e)
    {
        if(stepCount == 0)
            //Ensuring that we never get into minus numbers
            stepCount = 0;
    
        stepCount--;
    
        DAL.TicketsDataSetTableAdapters.TicketDetailsTableAdapter eobj = new DAL.TicketsDataSetTableAdapters.TicketDetailsTableAdapter();
        DataTable dt = new DataTable();
        dt = eobj.GetTicketUpdates(txtSupportRef.Text);
    
        txtNextStep.Text = eobj.GetTicketData(txtSupportRef.Text).Rows[0][stepCount].ToString();
    }
    
    protected void btnNext_Click1(object sender, EventArgs e)
    {
        if(stepCount == 0)
            //Ensuring that we never get into minus numbers
            stepCount = 0;
    
        stepCount++;
    
        DAL.TicketsDataSetTableAdapters.TicketDetailsTableAdapter eobj = new DAL.TicketsDataSetTableAdapters.TicketDetailsTableAdapter();
        DataTable dt = new DataTable();
        dt = eobj.GetTicketUpdates(txtSupportRef.Text);
    
        txtNextStep.Text = eobj.GetTicketData(txtSupportRef.Text).Rows[0][stepCount].ToString();
    }
    

    您还可以在单​​击下一步按钮时添加一个检查,以检查用户当前是否在最后一条记录上,如果是,则再次将其发送到记录列表的开头。

    【讨论】:

    • stepCount 是在哪里定义的?
    【解决方案5】:

    您希望缓存查找结果,而不是在视图代码中执行此操作,并且仅在有其他项目时才显示“下一步”按钮。

    为此,为它们创建一个容器对象。

    假设你的数据是这样的

    class Ticket
    {
         public string SomeField{get;set;}
    }
    

    制作一个类似的容器

    class TicketList
    {
        private List<Ticket> _tickets;
        private int _currentPosition;
        public TicketList<IEnumerable<Ticket> tickets>
        {
            _tickets = ticket;
            _currentPosition = 0;
        }
    
        public Ticket GetCurrent()
        {
            return _tickets[_currentPosition];
        }
    
        public bool CanMoveNext{
            get{
                return _tickets.Any() && _currentTicket != _tickets.Count - 1;
            }
        }
    
    
        public Ticket GetNext()
        {
            _currentPosition++;
            return _tickets[_currentPosition];
        }
    }
    

    所以现在当您加载应用程序时,您会将票证加载到缓存中

    var tickets = new List<Ticket>();
    var data = eobj.GetTicketData(txtSupportRef.Text);
    foreach(var row in data.Rows)
    {
        var ticket = new Ticket{ 
            //map over the ticket data here, or use AutoMapper
        };
        tickets.Add(ticket);
    }
    
    var ticketList = new TicketList(tickets);
    Cache.Store(ticketList);  //cache can be an application var, or better solution
    

    在页面加载时,您可以执行 var ticketList = Cache.GetTicketList(); btnNext.Visible = ticketList.CanMoveNext; var ticket = ticketList.GetCurrent(); //populate your fields

    现在除了不会在每次页面加载时重新加载所有票证之外,您的代码将来会更容易维护。

    【讨论】:

      猜你喜欢
      • 2011-01-03
      • 2012-02-05
      • 1970-01-01
      • 2013-09-14
      • 2019-02-18
      • 1970-01-01
      • 2018-08-09
      • 2015-10-05
      • 1970-01-01
      相关资源
      最近更新 更多