asp:CustomValidator/OnServerValidate

У меня есть CheckBoxList, который я пытаюсь проверить, установлен ли хотя бы один из флажков.

Разметка:

<asp:CustomValidator ID="RequiredFieldValidator8" ValidationGroup="EditArticle"
    runat="server" ErrorMessage="At least one Category is required."
    OnServerValidate="topic_ServerValidate" />
<asp:CheckBoxList id="checkboxlistCategories" runat="server"></asp:CheckBoxList>

Код программной части:

protected void topic_ServerValidate(object source, ServerValidateEventArgs args)
{
    int i = 0;
    foreach (ListItem item in checkboxlistCategories.Items)
    {
        if (item.Selected == true)
            i = i + 1;
    }
    if (i == 0)
        args.IsValid = false;
    else
        args.IsValid = true;
}

Если я добавлю ControlToValidate="checkboxlistCategories" в элемент управления CustomValidator, он взорвется! Исключение, которое я получаю:

System.Web.HttpException: элемент управления «checkboxlistCategories», на который ссылается свойство ControlToValidate объекта «RequiredFieldValidator8».

Я что-то упускаю?


person Community    schedule 23.03.2010    source источник
comment
Возможно, вы захотите добавить описание того, как он взрывается. Если отображается какое-либо сообщение об ошибке, добавление его к вопросу повысит вероятность того, что другие найдут эту страницу, когда столкнутся с той же проблемой.   -  person Jørn Schou-Rode    schedule 23.03.2010
comment
исключение, которое я получаю: System.Web.HttpException: элемент управления «checkboxlistCategories», на который ссылается свойство ControlToValidate «RequiredFieldValidator8», не может быть проверен.   -  person    schedule 23.03.2010


Ответы (5)


Вот более чистая реализация jQuery, которая позволяет использовать одну ClientValidationFunction для любого количества элементов управления CheckBoxList на странице:

function ValidateCheckBoxList(sender, args) {
 args.IsValid = false;

 $("#" + sender.id).parent().find("table[id$="+sender.ControlId+"]").find(":checkbox").each(function () {
     if ($(this).attr("checked")) {
  args.IsValid = true;
  return;
     }
 });
}

Вот разметка:

<asp:CheckBoxList runat="server"
    Id="cblOptions" 
    DataTextField="Text" 
    DataValueField="Id" />

<xx:CustomValidator Display="Dynamic" 
        runat="server" 
        ID="cblOptionsValidator"
        ControlId="cblOptions"
        ClientValidationFunction="ValidateCheckBoxList" 
        ErrorMessage="One selection required." />

И, наконец, пользовательский валидатор, который позволяет клиентской функции получить целевой элемент управления по идентификатору:

public class CustomValidator : System.Web.UI.WebControls.CustomValidator
{
 public string ControlId { get; set; }

 protected override void OnLoad(EventArgs e)
 {
     if (Enabled)
         Page.ClientScript.RegisterExpandoAttribute(ClientID, "ControlId", ControlId);

     base.OnLoad(e);
 }
}
person Nariman    schedule 25.10.2010

Учитывая, что ваш метод проверки на стороне сервера topic_ServerValidate привязан конкретно к полю checkboxlistCategories, вам не нужно устанавливать свойство ControlToValidate.

Причина, по которой он «взрывается» при добавлении свойства ControlToValidate, заключается в типе элемента управления, на который вы ссылаетесь, — CheckBoxList. При назначении ControlToValidate любому типу валидатора этот валидатор автоматически выполнит «непустую» проверку элемента управления, на который ссылаются, перед выполнением фактической логики проверки. Если поле пусто, проверка не выполняется (т. е. проверка выполнена успешно). Это, конечно, если вы не установите ValidateWhenEmpty = true. Видимо, валидаторы не знают, как проверить, пуст ли CheckBoxList, и вместо этого выбрасывают исключение.

В вашем конкретном случае, когда CustomValidator действительно просто служит непустой проверкой, вы определенно хотите, чтобы валидатор выполнялся, даже если указанный элемент управления остается «пустым». Как указано в первом абзаце моего ответа, самый простой способ добиться этого - удалить оскорбительное и ненужное свойство.

person Jørn Schou-Rode    schedule 23.03.2010
comment
когда я пытался без ControlToValidate=checkboxlistCategories, метод OnServerValidate не срабатывал. - person ; 23.03.2010
comment
@Нил: ты уверен? Я только что протестировал урезанную форму, содержащую CustomValidator (только с установленным обработчиком событий ServerValidate), CheckBoxList и Button. Нажатие кнопки обязательно запускает здесь обработчик событий проверки. - person Jørn Schou-Rode; 23.03.2010
comment
Если я добавлю Page.Validate() в page_load в if (!IsPostBack) и событие OnServerValidate срабатывает каждый раз, но не в (IsPostBack) или в событии нажатия кнопки - person ; 24.03.2010
comment
@Neil: я не уверен, что полностью тебя понимаю. Почему вы называете Page.Validate() явно? Проверка должна происходить автоматически при нажатии кнопки, и вам нужно только проверить, есть ли Page.IsValid в обработчике события нажатия. - person Jørn Schou-Rode; 24.03.2010
comment
Я вызываю Page.Validate() в событии кнопки прямо перед Page.IsValid, чтобы убедиться, что событие на стороне сервера выполнено. Любая идея? - person ; 24.03.2010
comment
Если у вас нет CausesValidation = false на Button, вам не нужно явно вызывать Page.Validate(). - person Jørn Schou-Rode; 25.03.2010

Просто предложение, но вместо этого вы можете использовать переключатели и определить имя группы. Это устранило бы необходимость проверки, потому что в группе можно проверить только один переключатель.

person Eric    schedule 23.03.2010
comment
Код в вопросе установит IsValid, если установлен один или несколько флажков. Радиокнопки будут принимать только один для выбора в любое время. - person Jørn Schou-Rode; 23.03.2010

Может быть, я что-то упускаю. Но CheckBoxList элемент управления не имеет ValidationPropertyAttribute. Таким образом, вы не можете использовать его как свойство ControlToValidate. Попробуй это:

CheckBoxList.cs

[ValidationProperty("SelectedIndex")]
public class CheckBoxList : System.Web.UI.WebControls.CheckBoxList
{
}

Web.Config

<tagMapping>
  <add tagType="System.Web.UI.WebControls.CheckBoxList, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" mappedTagType="Namespace.CheckBoxList, Assembly"/>
</tagMapping>

Во всяком случае, Скотт Митчелл написал об этом отличную статью здесь.

person Mehdi Golchin    schedule 23.03.2010

Как упомянул Мехди, 4 парня рассказали об этом в статье, на которую он ссылается в своем ответе.

Для краткости вот листинг кода:

public class CheckBoxListRequiredFieldValidator : BaseValidator
{
    private ListControl _listctrl;

    public CheckBoxListRequiredFieldValidator()
    {
        base.EnableClientScript = false;
    }

    protected override bool ControlPropertiesValid()
    {
        Control ctrl = FindControl(ControlToValidate);

        if (ctrl != null)
        {
            _listctrl = (ListControl)ctrl;
            return (_listctrl != null);
        }
        else
            return false;  
    }

    protected override bool EvaluateIsValid()
    {
        return _listctrl.SelectedIndex != -1;
    }
}

Вставьте этого барсука в свою библиотеку пользовательских элементов управления и вперед.

ХТН.

person EightyOne Unite    schedule 17.06.2010