views:

581

answers:

8

Hey there, i got this very annoying problem: I have a CheckBoxList getting items from a datasource with it's values and all. What I need is to show some panel when Item with value "33" is Checked. So I Need to get the Clicked Item, Last Clicked, or something... I tried a lot of ways and it just won't work... None of the following 3 lines can get me the Value i need:

protected void chkServicos_SelectedIndexChanged(object sender, EventArgs e)
    {
          //
          // Just trying to get the "clicked" value
          //

          CheckBoxList cbl = sender as CheckBoxList;
          Response.Write(cbl.SelectedIndex);
          Response.Write(cbl.SelectedItem);
          Response.Write(cbl.SelectedValue);
    }
A: 

Try this:

cbl.SelectedItem.Checked that should return true / false
cbl.SelectedItem.Text that should return the actual string
cbl.SelectedValue.Text that should return the value bound
JonH
cbl.SelectedItem returns a VALUE, so it doesn't even have the ".Checked" verification
Vitor Reis
Thanks again, but that doesn't give me the item that I just clicked... if I have other items selected, .SelectedItem and SelectedValue will be all messed up
Vitor Reis
A: 

Try hardcoding:

<asp:ListItem value="33">This Item</asp:ListItem>

This should make cbl.SelectedValue equal to the string "33". If that works, update your databinding to ensure that the value of your listitems is bound to the correct data member.

Dave Swersky
+2  A: 

Your doing something wrong. Most likely you are assuming 33 will be the value of .SelectedValue. If you have multiple items in the list the SelectedValue will only yield the first selected. This code works:

 <form id="form1" runat="server">
    <asp:CheckBoxList ID="CheckBoxList1" runat="server" 
        onselectedindexchanged="CheckBoxList1_SelectedIndexChanged">
        <asp:ListItem Value="33">33</asp:ListItem>
        <asp:ListItem Vaue="Not 33">Not 33</asp:ListItem>
    </asp:CheckBoxList>
    <asp:Button ID="Button1" runat="server" onclick="Button1_Click" Text="Button" />
    </form>

  protected void CheckBoxList1_SelectedIndexChanged(object sender, EventArgs e)
    {
        Response.Write((sender as CheckBoxList).SelectedValue); // prints 33 if 33 is selected
    }

Of course, if you have multiple items selected in the list, the result might not be what you expected. You might consider something like:

  ListItem selected33 = CheckBoxList1.Items.Cast<ListItem>()
  .Where(item => item.Value == "33" && item.Selected).SingleOrDefault();

    if (selected33 != null)
    {
        Response.Write("33 is selected");
    }
RichardOD
Hmm.. your code was able to show the panel that i needed.. but after item 33 is selected and I select another item, the panel shows up again and again
Vitor Reis
Then it sounds like you need to hide the panel when the logic changes!
RichardOD
+1  A: 

You might need to store a collection of your checked values and then when that event is fired, do a diff between the selected items and your collection. That checkboxList's selected item and value properties are always going to return the 1st item in it's collection of selected items.

JPero
A: 
CheckBoxList cbl = sender as CheckBoxList;
ListItem item = cbl.Items.FindByValue("33");
if (item != null && item.Selected) 
{
  //Show Panel
}
JPero
this way, every other time that SelectedIndexChanged triggers, and my item still selected, the pannel will show up
Vitor Reis
+1  A: 

I can't really tell from your question, but my guess is that you're probably resetting the value of the checkbox before the SelectedIndexChanged event is handled by your method (I've done that before!).

Before that handler gets called, the page has to be completely rebuilt on the server from ViewState, so the Page_Load and Page_Init methods are called (amongst others). If you're binding the values to your list during either of these method handlers, you'll end up overwriting the list options and the selected index will reset to the default value. Alternatively, you might be setting the default selected index in one of these methods. To prevent this from happening, make sure that you bind your data source in an if like such:

if (!Page.IsPostBack) { .. }
Dexter
Yeah, that happens when using assynchronous requests.. my Load method for the CheckBoxList is already inside if(!Page.IsPostback)
Vitor Reis
+1  A: 

If you're not against some javascript, this could work:

ASPX

<div>
        <asp:HiddenField ID="cblLastChecked" runat="server" Value="" />
        <asp:CheckBoxList ID="cbl" runat="server" AutoPostBack="true" >
            <asp:ListItem Text="11" Value="11"></asp:ListItem>
            <asp:ListItem Text="22" Value="22"></asp:ListItem>
            <asp:ListItem Text="33" Value="33"></asp:ListItem>
        </asp:CheckBoxList>
    </div>

<script language="javascript">
    function CheckBoxListClickHandler(sender) {
        //the sender is the checkbox, but the value is in a label below
        var label = sender.nextSibling;
        var lastChecked = document.getElementById("cblLastChecked");
        if(label != null && lastChecked != null) 
        { 
            lastChecked.value = label.innerText;
        }
        //alert(lastChecked.value);
    }
</script>

CS

protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);

            foreach (ListItem item in this.cbl.Items)
            {
                item.Attributes.Add("onclick", "javascript:CheckBoxListClickHandler(this)");
            }

            this.cbl.SelectedIndexChanged += new EventHandler(list_SelectedIndexChanged);
        }

        void list_SelectedIndexChanged(object sender, EventArgs e)
        {
            string targetValue = "33";
            if (this.cblLastChecked.Value == targetValue)
            {
                ListItem item = this.cbl.Items.FindByValue(targetValue);
                if (item != null && item.Selected)
                {
                    //Show Panel
                }
                else
                {
                    //hide panel
                }
            }
        }
JPero
+1  A: 

On Page Load:

if (!Page.IsPostBack)
    {

        ViewState["Clicked"] = false;
    }

SelectedChanged:

CheckBoxList clicked = (CheckBoxList)sender;
    bool selected = clicked.Items.FindByValue("33").Selected;

    if (selected)
    {
        if (Convert.ToBoolean(ViewState["Clicked"]) == false)
        {
            //do something
            ViewState["Clicked"] = true;
        }
    }
    else
    {
        ViewState["Clicked"] = false;
    }
Ricardo M Machado
Simple trick that got it done! thanks
Vitor Reis