【问题标题】:Why do I have to click a button twice in an ASP.NET repeater to get the command to fire?为什么我必须在 ASP.NET 中继器中单击两次按钮才能触发命令?
【发布时间】:2012-05-17 13:53:24
【问题描述】:

我有一个包含以下 3 个主要区域的 ASP.NET 页面:

1 - 左侧用于过滤结果的复选框列表

2 - 在中间显示匹配结果的中继器(每个项目都有一个按钮)

3 - 在右侧显示所选项目的中继器

在初始页面加载时,页面将显示数据绑定复选框并显示所有结果(因为没有在过滤器中检查任何内容)。当用户选中或取消选中复选框时,页面将重新加载并且匹配结果将发生变化。到目前为止,这部分效果很好。

在结果重复器中,每个项目都有一个按钮。当用户单击结果中某个项目的按钮时,想法是该项目将被添加到右侧的 Selected Repeater 中。发生的情况是,在我选中或取消选中过滤器复选框后 - 第一次 次我尝试单击结果中继器中的按钮,但没有任何反应。页面只是重新加载。然后,如果我再次单击该按钮,Repeater 命令将触发,并且该项目将被添加到右侧的 Repeater。然后,只要我不更改任何复选框,我就可以单击其中一个命令按钮,它会立即工作。但是,如果我选中过滤器区域中的一个复选框(这会导致结果重新绑定),那么我必须单击其中一个按钮两次才能触发它。

我感觉这与 ViewState 有关,但我不知道。有谁知道为什么会这样?

下面是我的 ASPX 页面代码和后面的代码。

ASPX 代码:

<h3>Filters</h3>
<asp:Repeater ID="rptTechnologies" runat="server" OnItemDataBound="rptFacet_ItemDataBound">
  <HeaderTemplate><h4>Technology</h4></HeaderTemplate>
  <ItemTemplate><asp:CheckBox ID="chkFacet" runat="server" AutoPostBack="true" OnCheckedChanged="chkFacet_Changed" /><br /></ItemTemplate>
</asp:Repeater>
<asp:Repeater ID="rptVerticals" runat="server" OnItemDataBound="rptFacet_ItemDataBound">
  <HeaderTemplate><h4>Vertical</h4></HeaderTemplate>
  <ItemTemplate><asp:CheckBox ID="chkFacet" runat="server" AutoPostBack="true" OnCheckedChanged="chkFacet_Changed" /><br /></ItemTemplate>
</asp:Repeater>
<asp:Repeater ID="rptIndustries" runat="server" OnItemDataBound="rptFacet_ItemDataBound">
  <HeaderTemplate><h4>Industry</h4></HeaderTemplate>
  <ItemTemplate><asp:CheckBox ID="chkFacet" runat="server" AutoPostBack="true" OnCheckedChanged="chkFacet_Changed" /><br /></ItemTemplate>
</asp:Repeater>
<asp:Repeater ID="rptSolutions" runat="server" OnItemDataBound="rptFacet_ItemDataBound">
  <HeaderTemplate><h4>Solution</h4></HeaderTemplate>
  <ItemTemplate><asp:CheckBox ID="chkFacet" runat="server" AutoPostBack="true" OnCheckedChanged="chkFacet_Changed" /><br /></ItemTemplate>
</asp:Repeater>

<h3>Results</h3>
<asp:Repeater ID="rptMatchingSlides" runat="server" OnItemDataBound="rptMatchingSlides_ItemDataBound" OnItemCommand="rptMatchingSlides_Command">
  <ItemTemplate>
    <h4><asp:Literal ID="litName" runat="server"></asp:Literal></h4>
    <asp:Button ID="btnSelect" runat="server" Text="Select" CommandName="Select" />
  </ItemTemplate>
  <SeparatorTemplate><hr /></SeparatorTemplate>
</asp:Repeater>

<h3>Selected</h3>
<asp:Repeater ID="rptSelectedSlides" runat="server" OnItemDataBound="rptSelectedSlides_ItemDataBound">
  <ItemTemplate>
    <h4><asp:Literal ID="litName" runat="server"></asp:Literal></h4>
  </ItemTemplate>
  <SeparatorTemplate><hr /></SeparatorTemplate>
</asp:Repeater>

下面是代码:

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Page.IsPostBack)
        {
            this.BindData();
        }
    }

    public List<string> SelectedSlides
    {
        get 
        {
            if (Session["SelectedIDs"] != null)
            {
                string[] _ids = Session["SelectedIDs"].ToString().Split(new char[] { '|' });
                List<String> _retVal = new List<string>();
                foreach (string _id in _ids)
                {
                    _retVal.Add(_id);
                }
                return _retVal;
            }
            else 
            {
                return new List<string>();
            }
        }
        set 
        {
            //Set the session value
            string _val = "";
            foreach (string _id in value)
            {
                if (_val == "")
                {
                    _val = _id;
                }
                else 
                {
                    _val += "|" + _id;
                }
            }
            Session["SelectedIDs"] = _val;
        }
    }


    protected void BindData()
    {
        //Filters
        rptTechnologies.DataSource = Repository.GetTaxonomyItems();
        rptTechnologies.DataBind();

        rptVerticals.DataSource = Repository.GetTaxonomyItems();
        rptVerticals.DataBind();

        rptIndustries.DataSource = Repository.GetTaxonomyItems();
        rptIndustries.DataBind();

        rptSolutions.DataSource = Repository.GetTaxonomyItems();
        rptSolutions.DataBind();

        this.BindMatchingSlides();
    }

    protected void BindMatchingSlides()
    {
    ...build list of ids from checkboxes...

        rptMatchingSlides.DataSource = Repository.GetMatchingSlides(_selectedIDs);
        rptMatchingSlides.DataBind();
    }

    protected void BindSelectedSlides()
    {
        if (this.SelectedSlides.Count > 0)
        {
            rptSelectedSlides.DataSource = this.SelectedSlides;
            rptSelectedSlides.DataBind();
        }
        else 
        {
            divSelectedSlides.Visible = false;
        }
    }

    protected void rptMatchingSlides_ItemDataBound(object sender, RepeaterItemEventArgs e)
    {
        if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
        {
            Literal _litName = (Literal)e.Item.FindControl("litName");
            Button _btnSelect = (Button)e.Item.FindControl("btnSelect");

            _litName.Text = ...set name here...

            _btnSelect.CommandArgument = ...use unique ID of item from database...
            _btnSelect.ID = "btnSelect_" + e.Item.ItemIndex;
        }
    }

    protected void rptMatchingSlides_Command(object sender, RepeaterCommandEventArgs e)
    {
        if (e.CommandName == "Select")
        {
            Item _slide = ...get data from database based on Command Argument...
            if (_slide != null)
            {
                List<string> _selectedSlides = this.SelectedSlides;
                _selectedSlides.Add(_slide.ID.ToString());
                this.SelectedSlides = _selectedSlides;
            }
            this.BindSelectedSlides();
        }
    }

【问题讨论】:

  • 您是否 100% 确定您的 rptMatchingSlides_Command 第一次不会触发,但在您第二次单击结果中继器中的按钮时会触发?换句话说,你在那里设置了断点吗?
  • 是的。我已将其放入调试中,第一次单击该按钮时,我看到页面加载触发,但没有触发 rptMatchingSlides_Command。然后当我第二次单击该按钮时,它会触发。
  • 有趣...想知道它是否会丢失其事件信息。试试这个,删除 _btnSelect.ID = 代码,看看是否有帮助......仅供参考,这不是必需的,因为按钮将自动唯一命名。

标签: asp.net repeater


【解决方案1】:

感谢 Jeremy - 删除了我设置 ID 的代码行来修复它。嗬!我在其他地方读到过,您需要为中继器中按钮的 ID 设置一个唯一值。所以这一定是罪魁祸首。感谢杰里米。

【讨论】:

  • 出色的工作!这里有一些关于“独特”主题的阅读:INamingContainer Interface
  • 救命稻草!在阅读其他帖子后,我也在做同样的事情。 :P
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-29
  • 2015-07-02
  • 2021-12-30
  • 1970-01-01
  • 1970-01-01
  • 2021-11-11
相关资源
最近更新 更多