2009-11-02 1 views
0

Я пытаюсь создать настраиваемый элемент управления, который расширяет RadComboBox от Telerik, чтобы создать список флажков Dropdown с шаблонами по умолчанию. План состоит в том, чтобы использовать элемент управления в нескольких местах, поэтому я хотел объединить всю логику в одном месте.ASP.NET Server Control на основе RadComboBox - проблема с обратной записью

Однако я переживаю пару странных вопросов по обратной передаче. Если вы проверите несколько элементов, а затем нажмите кнопку «Применить», будут выбраны правильные элементы, но текст в этом флажке будет отличаться. Затем на следующей обратной передаче я получаю сообщение об ошибке Multiple controls with the same ID 'i2' were found. FindControl requires that controls have unique IDs.

Прикрепленный пользовательский элемент управления. Любая помощь приветствуется.

C# Код:

/// <summary> 
/// Private Header template class for the DropdownCheckboxList 
/// </summary> 
class CheckboxListFooterTemplate : ITemplate 
{ 
    #region Public Methods 

    public void InstantiateIn(Control container) 
    { 
     string footer = "<input type=\"submit\" value=\"Apply\" />"; 
     container.Controls.Add(new LiteralControl(footer)); 
    } 

    #endregion Public Methods 
} 

/// <summary> 
/// Private Header template class for the DropdownCheckboxList 
/// </summary> 
class CheckboxListHeaderTemplate : ITemplate 
{ 
    #region Public Methods 

    public void InstantiateIn(Control container) 
    { 
     string header = "<input type=\"button\" value=\"Check All\" onclick=\"CheckAll(&quot;{0}&quot;, true)\" />"; 
     header += "&nbsp;<input type=\"button\" value=\"Uncheck All\" onclick=\"CheckAll(&quot;{0}&quot;, false)\" />"; 

     container.Controls.Add(new LiteralControl(string.Format(header, container.Parent.ClientID))); 
    } 

    #endregion Public Methods 
} 

/// <summary> 
/// Template class for the DropdownChecklistBox 
/// </summary> 
class CheckboxListTemplate : ITemplate 
{ 
    #region Constants 

    //this div will stop the list from closing as a listitem is clicked 
    const string head = "<div onclick=\"StopPropagation(event)\" class=\"combo-item-template\">"; 
    const string tail = "</div>"; 

    #endregion Constants 

    #region Private Methods 

    /// <summary> 
    /// Bind the data to the checkbox 
    /// </summary> 
    /// <param name="sender">Checkbox to bind data to</param> 
    /// <param name="e"></param> 
    private void checkbox_DataBinding(object sender, EventArgs e) 
    { 
     CheckBox target = (CheckBox)sender; 
     RadComboBoxItem item = (RadComboBoxItem)target.BindingContainer; 
     string itemText = (string)DataBinder.Eval(item, "Text"); 
     target.Text = itemText; 
    } 

    #endregion Private Methods 

    #region Public Methods 

    /// <summary> 
    /// Create the checkbox list items in the template 
    /// </summary> 
    /// <param name="container">Container that the control will be added</param> 
    public void InstantiateIn(Control container) 
    { 
     CheckBox checkbox = new CheckBox(); 
     checkbox.ID = "chkList"; 
     checkbox.Attributes.Add("onclick", string.Format("onCheckBoxClick(this, \"{0}\")", container.Parent.ClientID)); 

     container.Controls.Add(new LiteralControl(head)); 
     checkbox.DataBinding += new EventHandler(checkbox_DataBinding); 
     container.Controls.Add(checkbox); 

     container.Controls.Add(new LiteralControl(tail)); 
    } 

    #endregion Public Methods 
} 

//todo: complete summary 
/// <summary> 
/// based on telerik demo: http://demos.telerik.com/aspnet-ajax/combobox/examples/functionality/templates/defaultcs.aspx 
/// </summary> 
[DefaultProperty("Text")] 
[ToolboxData("<{0}:DropdownCheckboxList runat=server></{0}:DropdownCheckboxList>")] 
public class DropdownCheckboxList : RadComboBox, INamingContainer 
{ 
    #region Private Properties 

    string SelectedText 
    { 
     get 
     { 
      StringBuilder values = new StringBuilder(SelectedItems.Count); 
      foreach (RadComboBoxItem item in SelectedItems) 
       values.Append(item.Text + ", "); 

      if (values.Length > 0) 
       return values.ToString().Remove(values.Length - 2, 2); 
      else 
       return EmptyMessage; 
     } 
    } 

    #endregion Private Properties 

    #region Public Properties 

    public RadComboBoxItemCollection SelectedItems 
    { 
     get 
     { 
      CheckBox chk = null; 
      RadComboBoxItemCollection selectedItems = new RadComboBoxItemCollection(this); 

      foreach (RadComboBoxItem item in Items) 
      { 
       chk = (CheckBox)item.FindControl("chkList"); 
       if (chk != null && chk.Checked) 
        selectedItems.Add(item); 
      } 

      return selectedItems; 
     } 
    } 

    //todo: summary 
    public override string SelectedValue 
    { 
     get 
     { 
      StringBuilder values = new StringBuilder(SelectedItems.Count); 
      foreach (RadComboBoxItem item in SelectedItems) 
       values.Append(item.Value + ", "); 

      if (values.Length > 0) 
       return values.ToString().Remove(values.Length - 2, 2); 
      else 
       return ""; 
     } 
     set 
     { 
      if (value != null) 
       SelectedValues = new List<string>(value.Split(',')); 
     } 
    } 

    //todo: summary 
    public List<string> SelectedValues 
    { 
     get 
     { 
      List<string> selectedValues = new List<string>(); 

      foreach (RadComboBoxItem item in SelectedItems) 
      { 
       selectedValues.Add(item.Value); 
      } 

      return selectedValues; 
     } 
     set 
     { 
      RadComboBoxItem item = null; 
      CheckBox chk = null; 

      foreach (string val in value) 
      { 
       item = Items.FindItemByValue(val.Trim()); 

       if (item != null) 
       { 
        chk = (CheckBox)item.FindControl("chkList"); 

        if (chk != null) 
         chk.Checked = true; 
       } 
      } 
     } 
    } 

    #endregion Public Properties 

    #region Protected Methods 

    protected override void CreateChildControls() 
    { 
     if (base.HeaderTemplate == null) 
      base.HeaderTemplate = new CheckboxListHeaderTemplate(); 

     if (base.ItemTemplate == null) 
      base.ItemTemplate = new CheckboxListTemplate(); 

     if (base.FooterTemplate == null) 
      base.FooterTemplate = new CheckboxListFooterTemplate(); 

     base.CreateChildControls(); 
    } 

    protected override void OnPreRender(EventArgs e) 
    { 
     base.OnPreRender(e); 
     string resourceName = "CustomControls.DropdownCheckboxList.js"; 

     ClientScriptManager cs = this.Page.ClientScript; 
     cs.RegisterClientScriptResource(typeof(CustomControls.DropdownCheckboxList), resourceName); 

     Text = SelectedText; 
    } 

    #endregion Protected Methods 
} 

Javascript Код:

//based on telerik demo: http://demos.telerik.com/aspnet-ajax/combobox/examples/functionality/templates/defaultcs.aspx 

    var cancelDropDownClosing = false; 

    function StopPropagation(e) { 
     //cancel bubbling 
     e.cancelBubble = true; 
     if (e.stopPropagation) { 
      e.stopPropagation(); 
     } 
    } 

    function onDropDownClosing() { 
     cancelDropDownClosing = false; 
    } 

    function CheckAll(comboBoxId, value) { 
     var combo = $find(comboBoxId); 

     //get the collection of all items 
     var items = combo.get_items(); 

     //enumerate all items 
     for (var i = 0; i < items.get_count(); i++) { 
      var item = items.getItem(i); 
      //get the checkbox element of the current item 
      var chk1 = $get(combo.get_id() + "_i" + i + "_chkList"); 
      chk1.checked = value; 
     } 
    } 

    function onCheckBoxClick(chk, comboBoxId) { 
     var combo = $find(comboBoxId); 
     //holds the text of all checked items 
     var text = ""; 
     //holds the values of all checked items 
     var values = ""; 
     //get the collection of all items 
     var items = combo.get_items(); 
     //enumerate all items 
     for (var i = 0; i < items.get_count(); i++) { 
      var item = items.getItem(i); 
      //get the checkbox element of the current item 
      var chk1 = $get(combo.get_id() + "_i" + i + "_chkList"); 
      if (chk1.checked) { 
       text += item.get_text() + ", "; 
       values += item.get_value() + ", "; 
      } 
     } 
     //remove the last comma from the string 
     text = removeLastComma(text); 
     values = removeLastComma(values); 

     if (text.length > 0) { 
      //set the text of the combobox 
      combo.set_text(text); 
     } 
     else { 
      //all checkboxes are unchecked 
      //so reset the controls 
      combo.set_text(""); 
     } 
    } 

    //this method removes the ending comma from a string 
    function removeLastComma(str) { 
     return str.replace(/,$/, ""); 
    } 

ответ

0

Эта линия в InstantiateIn(Control container) является основной причиной проблемы:

checkbox.ID = "chkList";

Эта линия делает каждый флажок есть один и тот же идентификатор - они должны быть уникальными.

Так может выглядеть следующим образом

checkbox.ID = Container.ID + SomeUniqueString;

Я создал проект с кодом, который вы предоставили, и продублировал ошибку только одним элементом управления на странице. (были и другие ошибки в javascript, но я был в состоянии игнорировать их.)

Я не мог найти простой способ создать уникальные идентификаторы, чтобы вы могли знать, что они должны делать. Таким образом, вместо этого:

chk = (CheckBox)item.FindControl("chkList"); 

Я попытался это:

foreach (var o in item.Controls) 
{ 
    if (o is CheckBox) 
    { 
     chk = (CheckBox) o; 
    } 
} 

Он устранил ошибку и позволил мне выбрать более одного пункта. Однако этот код не идеален - он делает предположение, что есть только один флажок. Вам было бы лучше убедиться, что идентификаторы уникальны. Подход, который я хотел бы использовать, заключается в том, чтобы основывать id на значении элемента combo box.

Если выбранные элементы фиксированы (пользователь не может добавлять новые элементы через поле со списком), вы можете попробовать использовать RadMenu. У нас очень симиарный контроль, но мы используем RadMenu. Мы просто устанавливаем изображение в пункте меню, чтобы указать статус выбора, и мы отслеживаем выбранные элементы в пределах нашего контроля.