3

I have created a custom server control, deriving from System.Web.Contols.CheckBoxList to customize how a CheckBoxList is rendered. I also wanted to add another bindable field and get the value of the field within the CheckBoxList.RenderItem() method. The field I want to create, should contain a value specifying whether a CheckBoxListItem is checked. I've read some articles regarding custom DataFields, but it never gets explained in detail.

I've included a portion of my class to better explain what I can't seem to understand.

public class ListedCheckBoxList : CheckBoxList
{
    protected override void RenderItem(ListItemType itemType, int repeatIndex, RepeatInfo repeatInfo, HtmlTextWriter writer)
    {
        if (itemType != ListItemType.Item)
            return;

        var item = base.Items[repeatIndex];

        string cbxHtml = string.Format("<input type=\"checkbox\" value=\"{0}\" name=\"{1}\" /> {2}",
            item.Value,
            string.Concat(this.ClientID, repeatIndex),
            item.IsChecked, // <-- My custom bindable field
            item.Text);

        writer.Write(cbxHtml);
    }
}

When using this control in the .aspx page, I'm attempting to bind it like this

<abc:ListedCheckBoxList ID="cbxList" runat="server"
     DataValueField="UserId"
     DataTextField="UserFullName"
     DataIsCheckedField="UserIsActive" />
sshow
  • 8,820
  • 4
  • 51
  • 82

2 Answers2

3

Here is a version I wrote a year or so ago. I wanted to be able to bind the checked status as well as a tooltip for the individual items. Hope it helps...

public class CheckBoxList_Extended : CheckBoxList
{
    /// <summary>
    /// Gets or sets the name of the data property to bind to the tooltip attribute of the individual CheckBox.
    /// </summary>
    [DefaultValue("")]
    public string DataTooltipField
    {
        get
        {
            string value = base.ViewState["DataTooltipField"] as string;
            if (value == null)
                value = "";
            return value;
        }
        set
        {
            if (value == null || value.Trim() == "")
            {
                base.ViewState.Remove("DataTooltipField");
            }
            else
            {
                base.ViewState["DataTooltipField"] = value.Trim();
            }
        }
    }
    /// <summary>
    /// Gets or sets the name of the data property to bind to the Checked property of the individual CheckBox.
    /// </summary>
    [DefaultValue("")]
    public string DataCheckedField
    {
        get
        {
            string value = base.ViewState["DataCheckedField"] as string;
            if (value == null)
                value = "";
            return value;
        }
        set
        {
            if (value == null || value.Trim() == "")
            {
                base.ViewState.Remove("DataCheckedField");
            }
            else
            {
                base.ViewState["DataCheckedField"] = value.Trim();
            }
        }
    }

    protected override void PerformDataBinding(System.Collections.IEnumerable dataSource)
    {
        if (dataSource != null)
        {
            string dataSelectedField = this.DataCheckedField;
            string dataTextField = this.DataTextField;
            string dataTooltipField = this.DataTooltipField;
            string dataValueField = this.DataValueField;
            string dataTextFormatString = this.DataTextFormatString;

            bool dataBindingFieldsSupplied = (dataTextField.Length != 0) || (dataValueField.Length != 0);
            bool hasTextFormatString = dataTextFormatString.Length != 0;
            bool hasTooltipField = dataTooltipField.Length != 0;
            bool hasSelectedField = dataSelectedField.Length != 0;

            if (!this.AppendDataBoundItems)
                this.Items.Clear();

            if (dataSource is ICollection)
                this.Items.Capacity = (dataSource as ICollection).Count + this.Items.Count;

            foreach (object dataItem in dataSource)
            {
                ListItem item = new ListItem();

                if (dataBindingFieldsSupplied)
                {
                    if (dataTextField.Length > 0)
                    {
                        item.Text = DataBinder.GetPropertyValue(dataItem, dataTextField, null);
                    }
                    if (dataValueField.Length > 0)
                    {
                        item.Value = DataBinder.GetPropertyValue(dataItem, dataValueField, null);
                    }
                }
                else
                {
                    if (hasTextFormatString)
                    {
                        item.Text = string.Format(CultureInfo.CurrentCulture, dataTextFormatString, new object[] { dataItem });
                    }
                    else
                    {
                        item.Text = dataItem.ToString();
                    }
                    item.Value = dataItem.ToString();
                }
                if (hasSelectedField)
                {
                    item.Selected = (bool)DataBinder.GetPropertyValue(dataItem, dataSelectedField);
                }
                if (hasTooltipField)
                {
                    string tooltip = DataBinder.GetPropertyValue(dataItem, dataTooltipField, null);
                    if (tooltip != null && tooltip.Trim() != "")
                    {
                        item.Attributes["title"] = tooltip;
                    }
                }
                this.Items.Add(item);
            }
        }
        base.PerformDataBinding(null);
    }
}
Rozwel
  • 1,990
  • 2
  • 20
  • 30
  • Great! I cant't understand how all those articles could make such mess about this. This is exactly what I was after. – sshow Mar 23 '11 at 18:35
  • I can't take all of the credit, I found a couple good articles that put me onto this technique. Unfortunately I did not take notes so I can't point anyone else back to them. =P – Rozwel Mar 23 '11 at 18:46
  • Such an incredibly old but useful reply. Looking at this, I feel it would be quite straightforward to create a `RadioButtonList` implementation that honors actual `ListItem` instances when binding when they are returned from the datasourse, instead of creating new ones with just value and text. That would solve a similar problem for me as I can easily transform my data into a `IEnumerable`. – julealgon Jun 23 '18 at 12:54
  • I went ahead with the idea above and created a control that honors `ListItem` instances. It ended up working quite nicely. See here for more details: https://stackoverflow.com/questions/50993969/how-do-i-declaratively-bind-selectedvalue-to-datasource-field/ – julealgon Jun 28 '18 at 19:58
0

Checkbox already has a property for that, "Checked"

http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.checkbox.checked.aspx

You can add a custom fairly easily though, just add a new public property. You can then set it programatically or in the aspx code.

public class ListedCheckBoxList : CheckBoxList
{
    public string CustomTag { get; set; }
    //...snip
}

<myControls:myCheckBox runat='server' Checked='True' CustomTag="123test" />
asawyer
  • 17,642
  • 8
  • 59
  • 87