Событие Radiobuttonlist не всегда срабатывает

#c# #asp.net #radio-button #radiobuttonlist

#c# #asp.net #переключатель #radiobuttonlist

Вопрос:

У меня есть radiobuttonlist с событием selectedindexchanged, которое обновляет функцию поиска. Один из элементов указан в aspx, а остальные являются добавленными элементами с привязкой к данным. Независимо от того, что я установил по умолчанию, этот элемент не запустит событие. Все остальные элементы будут запускать событие. Кроме того, кажется, что после выбора «мертвого» элемента событие вообще не срабатывает.

Как я могу отследить ошибку и исправить? Вот текущий код.

РЕДАКТИРОВАТЬ: Извините, если краткая версия ввела в заблуждение. Я не был уверен, что включить. Вот целая страница.

Все aspx:

      <%@ Page Language="C#" MasterPageFile="~/MSDS/MSDS.master" EnableEventValidation="false"
    AutoEventWireup="true" CodeFile="SearchMSDS.aspx.cs" Inherits="MSDS_ByDept" Title="NCLWeb - Search MSDS" %>

<%@ Register Assembly="SqlWhereBuilder" Namespace="UNLV.IAP.WebControls" TagPrefix="cc1" %>
<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="cc2" %>
<asp:Content ID="Content1" ContentPlaceHolderID="PageContent" runat="Server">
    <h2>
        <asp:Label ID="lblTitle" runat="server">Search Active MSDS</asp:Label></h2>
    <table class="style1">
        <tr>
            <td style="width: 435px" valign="top">
                <asp:Panel runat="server" ID="pnlSearch" DefaultButton="btnSearch">
                    <asp:TextBox ID="txtSimpleSearch" runat="server" Width="262px"></asp:TextBox>
                    <asp:Button ID="btnSearch" runat="server" Text="Search" Width="96px" OnClick="btnSearch_Click" />
                    <br />
                    <asp:LinkButton ID="btnAdvSearch" runat="server" OnClick="btnAdvSearch_Click" Font-Size="Small">Show Advanced Search</asp:LinkButton>
                </asp:Panel>
                <asp:Panel ID="pnlAdvSearch" runat="server" Width="635px" DefaultButton="btnRunAdvSearch">
                    <asp:Button ID="btnRunAdvSearch" runat="server" OnClick="btnRunAdvSearch_Click" Text="Advanced Search" />
                    <cc1:SqlWhereBuilder ID="SqlWhereBuilder1" runat="server" ClientCodeLocation="../JavaScripts/SqlWhereBuilder.js"
                        FieldsFile="../ConfigFiles/SearchMSDS.config" OperatorListsFile="../ConfigFiles/SearchMSDS.config"
                        ValueEntryFile="../ConfigFiles/SearchMSDS.config">
                    </cc1:SqlWhereBuilder>
                    <br />
                    <br />
                </asp:Panel>
                <cc2:CollapsiblePanelExtender ID="pnlAdvSearch_CollapsiblePanelExtender" runat="server"
                    CollapseControlID="btnAdvSearch" Collapsed="True" Enabled="True" ExpandControlID="btnAdvSearch"
                    TargetControlID="pnlAdvSearch">
                </cc2:CollapsiblePanelExtender>
            </td>
            <td valign="top">
                <asp:Panel ID="pnlStatus" runat="server">
                    <asp:RadioButtonList ID="rblStatus" runat="server" AppendDataBoundItems="True"
                        AutoPostBack="True" DataSourceID="SqlDataSource1" DataTextField="DisplayValue"
                        DataValueField="Value" OnSelectedIndexChanged="RadioButtonList1_SelectedIndexChanged"
                        RepeatDirection="Horizontal" CellPadding="3" CellSpacing="3" 
                        CausesValidation="True" Visible="True">
                        <asp:ListItem Selected="True">All</asp:ListItem>
                    </asp:RadioButtonList>
                </asp:Panel>
                <asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:NCLWebConnectionString %>"
                    SelectCommand="getOptionList" SelectCommandType="StoredProcedure">
                    <SelectParameters>
                        <asp:Parameter DefaultValue="msds_Status" Name="ListName" Type="String" />
                    </SelectParameters>
                </asp:SqlDataSource>
                <asp:UpdatePanel runat="server" ID="upd2">
                    <ContentTemplate>
                        <asp:Button ID="btnExport" runat="server" Text="Export Results" 
                            OnClick="btnExport_Click1" UseSubmitBehavior="False" />
                    </ContentTemplate>
                </asp:UpdatePanel>
            </td>
        </tr>
    </table>
    <asp:UpdatePanel ID="UpdatePanel1" runat="server">
        <ContentTemplate>
            <asp:UpdateProgress ID="UpdateProgress1" runat="server" DisplayAfter="100" DynamicLayout="False">
                <ProgressTemplate>
                    <img src="../images/loading.gif" alt="Loading..." style="text-align: center" />
                    <asp:Label ID="lblProgress" runat="server"></asp:Label></ProgressTemplate>
            </asp:UpdateProgress>
            <asp:GridView ID="gridResults" runat="server" DataSourceID="sqlMSDS" OnRowDataBound="GridView1_RowDataBound"
                AllowPaging="True" PageSize="25" AllowSorting="True" OnSelectedIndexChanged="gridResults_SelectedIndexChanged"
                AutoGenerateColumns="False" EmptyDataText="No matching MSDS Sheets." OnSorted="gridResults_Sorted">
                <Columns>
                    <asp:BoundField DataField="ID" HeaderText="ID" InsertVisible="False" Visible="false"
                        ReadOnly="True" SortExpression="ID" />
                    <asp:BoundField DataField="ChemicalTitle" HeaderText="ChemicalTitle" SortExpression="ChemicalTitle" />
                    <asp:BoundField DataField="Manufacturer" HeaderText="Manufacturer" SortExpression="Manufacturer" />
                    <asp:BoundField DataField="UsageDept" HeaderText="UsageDept" SortExpression="UsageDept" />
                    <asp:BoundField DataField="Notes" HeaderText="Notes" SortExpression="Notes" />
                    <asp:BoundField DataField="Health" HeaderText="Health" visible="false" SortExpression="Health" />
                    <asp:BoundField DataField="Fire" HeaderText="Fire"  visible="false" SortExpression="Fire" />
                    <asp:BoundField DataField="Reactivity" HeaderText="Reactivity"  visible="false" SortExpression="Reactivity" />
                    <asp:BoundField DataField="DateUpdated" HeaderText="DateUpdated" SortExpression="DateUpdated" />
                </Columns>
                <SelectedRowStyle BackColor="Yellow" />
            </asp:GridView>
            <asp:SqlDataSource ID="sqlMSDS" OnSelected="sqlMSDS_OnSelected" runat="server" ConnectionString="<%$ ConnectionStrings:NCLWebConnectionString %>"
                SelectCommand="SELECT [ID]
                                      ,[ChemicalTitle]
                                      ,[Manufacturer]
                                      ,[UsageDept]
                                      ,[Notes]
                                      ,[Health]
                                      ,[Fire]
                                      ,[Reactivity]
                                      ,[DateUpdated]
                                      FROM [msds_Sheets]" OnSelecting="sqlMSDS_Selecting"></asp:SqlDataSource>
        </ContentTemplate>
        <Triggers>
            <asp:AsyncPostBackTrigger ControlID="btnSearch" EventName="Click" />
            <asp:AsyncPostBackTrigger ControlID="btnRunAdvSearch" EventName="Click" />
            <asp:AsyncPostBackTrigger ControlID="rblStatus" EventName="SelectedIndexChanged" />
            <asp:AsyncPostBackTrigger ControlID="btnExport" EventName="Click" />
        </Triggers>
    </asp:UpdatePanel>
    <br />
</asp:Content>
  

И ошибка в коде:

     List<String> safeWords = new List<String>();

protected void Page_Load(object sender, EventArgs e)
{
    pnlStatus.Visible = User.IsInRole("msds_Admin");

    gridResults.DataKeyNames = new String[] { "id" };

    txtSimpleSearch.Focus();

    if (!IsPostBack)
    {
        safeWords.Add("delete");
        safeWords.Add("insert");
        safeWords.Add("update");
        safeWords.Add("set");
        safeWords.Add("exec");
        safeWords.Add("N'");

        sqlMSDS.SelectCommand  = " Where status = 0 ";

        Session["Sql"] = sqlMSDS.SelectCommand;

        try
        {
            Session["OriginalSQL"] = sqlMSDS.SelectCommand.Remove(sqlMSDS.SelectCommand.IndexOf("Where"));
        }
        catch (Exception)
        {
            Session["OriginalSQL"] = sqlMSDS.SelectCommand;
        }
    }
}

protected void RadioButtonList1_SelectedIndexChanged(object sender, EventArgs e)
        {
            ((Label)UpdateProgress1.FindControl("lblProgress")).Text = "Searching...";

            if (btnSearch.Visible)
            {
                btnSearch_Click(null, null);

                if (RadioButtonList1.SelectedValue != "All")
                {
                    sqlMSDS.SelectCommand  = " And Status = "   RadioButtonList1.SelectedValue;
                }
                else
                {
                    //Somehow force the grid to research using no status parameter
                    sqlMSDS.SelectCommand = Session["Sql"].ToString();
                }
            }
            else
            {
                btnRunAdvSearch_Click(null, null);

                if (RadioButtonList1.SelectedValue != "All")
                {
                    if (sqlMSDS.SelectCommand.Contains("Where"))
                    {
                        sqlMSDS.SelectCommand  = " And Status = "   RadioButtonList1.SelectedValue;
                    }
                    else
                    {
                        sqlMSDS.SelectCommand  = " Where Status = "   RadioButtonList1.SelectedValue;
                    }
                }
                else
                {
                    //Somehow force the grid to research using no status parameter
                    sqlMSDS.SelectCommand = Session["Sql"].ToString();
                }
            }
        }
  

Комментарии:

1. Ваша проблема неясна. То есть вы имеете в виду, что он вообще не выполняет обратную передачу или выполняет в определенных случаях? Вы установили контрольные точки в исходном коде и посмотрели, что происходит? Есть ли какая-либо проверка на странице? Если да, посмотрите, не мешают ли они. Вы можете проверить это, установив CausesValidation=»false для вашего RBL.

2. Обратная передача происходит во всех случаях, за исключением случаев, когда установлено значение по умолчанию. Нет проверок на странице.

3. Странно. т.е. Когда вы выбираете элемент «Все», который выглядит по умолчанию, правильно? Просто чтобы убедиться, что вы делаете это при правильном изменении, а не когда оно уже выбрано? И еще одна вещь, о которой я могу подумать, — это любой код javascript, вмешивающийся в этот конкретный элемент. Извините за догадки, но я не вижу никаких причин, по которым не следует выполнять обратную передачу только для одного элемента.

4. @gbs -Да, когда я выбираю «Все» в этом случае. Однако я попытался изменить значение по умолчанию и получил тот же результат с этим элементом. На странице нет никакого Javascript. Да, для проверки я выбирал одно из других значений, затем нажимал на значение по умолчанию, которое должно вызывать событие selectedindexchanged.

5. Извините, подсказки заканчиваются, и трудно сказать без отладки. Может быть, вы можете попробовать на совершенно новой странице. А при отладке вы пробовали устанавливать точки останова в Page_Load?

Ответ №1:

Вот что происходило со мной и исправление.

У меня был radiobuttonlist, которого не было на панели обновления, но который был определен как триггер для панели обновления. У меня также был определен onselectedindexchanged. В Radiobuttonlist был выбран первый атрибут listitem =»true», поэтому он будет выбран по умолчанию при загрузке страницы. Затем выбор второго элемента списка сработал нормально, повторная публикация и обновление панели обновления.

Однако повторный выбор первого элемента не вызвал событие onselectedindexchanged. Используя потрясающую утилиту Inspect Element в Firefox, я смог определить, что сервер генерирует html-элемент (проверено только для первого элемента списка по умолчанию). Но поскольку radiobuttonlist отсутствовал на панели обновления, атрибут checked = «проверено» для второго элемента никогда не записывался в браузер, даже несмотря на то, что на стороне клиента второй переключатель визуально казался выбранным. Следовательно, при выборе исходного элемента во второй раз onselectedindexchanged не запускался на стороне сервера, поскольку вновь выбранный индекс уже был указан как выбранный в событии POST.

Вы не увидите этой проблемы, если список находится внутри панели, которую вы хотите обновить, потому что обратная отправка приводит к тому, что браузер получает «новые» элементы с checked =»проверено» для вновь выбранного элемента. Из-за макета моей страницы было неудобно размещать их на одной панели, поэтому исправление для меня состояло в том, чтобы поместить radiobuttonlist в свою собственную маленькую панель обновления. Что бы ни сработало для вас, ответ заключается в том, чтобы убедиться, что radiobuttonlist находится на КАКОЙ-либо панели обновления, чтобы атрибут checked мог быть отправлен в браузер для каждого элемента при выборе.

Ответ №2:

Указан ли этот RadioButtonList как AsyncPostBackTrigger для другой панели обновления? Если это так, проверьте следующую ссылку: событие CheckedChanged не срабатывает для переключателя в UpdatePanel

Я воспроизвел это поведение и исправил это с помощью следующего скрипта:

  $(function () {
        $("input[type='radio']:first", $("#<%= RadioButtonList1.ClientID %>")).attr("checked", true);
    });
  

если вы не можете использовать jQuery, попробуйте этот javascript:

  window.onload = function () {
        window.document.getElementById("<%= RadioButtonList1.ClientID %>_0").checked = true;
    };


protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            ClientScript.RegisterStartupScript(this.GetType(), "RadioButtonListDefaultValue", String.Format("window.document.getElementById('{0}_0').checked = true;", RadioButtonList1.ClientID), true);
        }
    }
  

Комментарии:

1. Это jQuery? Я не использовал ничего подобного в этом проекте.

2. @1stein вы предполагаете, что он использует UpdatePanel ? Или я что-то пропустил?

3. Исправьте это только по той причине, что я обнаружил, что значение по умолчанию, отмеченное по умолчанию, не запускает событие OnSelectedIndexChanged.

4. Правильно. Кроме того, если у вас есть элементы управления, которые могут запускать неасинхронную обратную отправку, вы должны добавить этот скрипт на стороне сервера в событии Page_Load вместо добавления скрипта в разметку страницы. У меня есть обновленный ответ на эту ситуацию.

5. На самом деле, у вас есть несколько способов исправить эту ошибку один раз, а затем использовать обычное поведение. Первый — написать пользовательский элемент управления, наследовать его из RadioButtonList и затем использовать его. Второе — реализовать адаптер для содержимого RadioButtonList. Хитрость заключается в удалении выбранного значения свойства и регистрации соответствующего javascript. Посмотрите решение для пользовательского элемента управления здесь: pastebin.com/UJa6JPVc

Ответ №3:

Как сказал пользователь user2965308, если RadioButtonList находится внутри UpdatePanel, этой проблемы не возникает.

https://www.codeproject.com/Questions/118042/RadioButtonList-Postback-issue-when-selected-by-co «Получите его внутри панели обновления, со свойством «ChildrenAsTriggers» в true. Это решает проблему для меня.»

Ответ №4:

 <asp:ListItem Selected="True">All</asp:ListItem>
  

Нажатие «Все» не изменяет выбранный индекс, поскольку этот элемент уже был выбран, поэтому событие не запускается. Выбор любого другого параметра изменяет выбранный параметр и вызывает запуск события. Я полагаю, ваша цель — отображать результаты для всех статусов при нажатии на «Все». Вы должны выполнить одно из следующих действий:

  • Отобразите эти результаты при первоначальной загрузке страницы, поскольку «Все» уже выбрано.
  • Добавьте кнопку «Поиск», которая инициирует отправку обратно вместо использования автоматической отправки переключателя.
  • Замените RadioButtonList выпадающим списком и присвойте ему два начальных списка: «Выбрать статус», значение которого является пустой строкой, и «Все», значение которого равно «All». Фиктивная запись «Выбрать статус» будет выглядеть менее неуместно в выпадающем списке, чем в RadioButtonList.

Из перечисленных выше вариантов я лично предпочел бы кнопку «Поиск», потому что автопостбэк раздражает меня как пользователя. Я ненавижу выпадающие списки автоматической отправки, из-за которых веб-страница сходит с ума, когда я случайно использую колесико мыши, когда список находится в фокусе.

Комментарии:

1. У меня действительно есть кнопка поиска, но я хочу, чтобы результаты поиска автоматически обновлялись при смене переключателей. Кроме того, я полагаю, что вы не совсем понимаете мою проблему: когда я выбираю другой вариант, а затем ВОЗВРАЩАЮСЬ к варианту по умолчанию, именно здесь я не получаю событие.

2. Кроме того, я бы очень хотел, чтобы radiobuttonlist работал, поскольку это имеет смысл визуально, и мне нравится этот дизайн. На самом деле я не заинтересован в замене radiobuttonlist, особенно потому, что он должен быть способен это сделать.