tags:

views:

276

answers:

5

I have a data-bound, templated control, and inside the templated area I create a control with an event handler, like so:

<tnl:DisplayTree ID="DisplayTree1" runat="server" KeyPropertyName="Id" 
ParentPropertyName="ParentDemographic" DataSourceID="DemographicObjectSource">
<ItemTemplate>
    <asp:CheckBox ID="DemogSelector" runat="server" OnCheckedChanged="DemogSelector_OnCheckedChanged" /> &nbsp;
    <asp:Label ID="InlineEditLabel" runat="server" Text='<%#DataBinder.Eval(Container.DataItem, "Name") %>'></asp:Label>
    </ItemTemplate>
</tnl:DisplayTree>

Within the event handler, I would like to be able to detect the Key of the item for which the control was created. For example:

protected void DemogSelector_OnCheckedChanged(object sender, EventArgs e)
{
    CheckBox selector = (CheckBox)sender;
    DisplayTree.TreeNode treeNode = (DisplayTree.TreeNode)selector.Parent.Parent.Parent.Parent;
    Label1.Text += (int)treeNode.Key + ", ";
}

As you can see, this approach requires close knowledge of the hierarchy within my DisplayTree.TreeNode class (i.e. I have to know that sender.Parent.Parent.Parent.Parent is where I'll find the DisplayTree.TreeNode object). I would like to make it a bit more robust, so that if my TreeNode hierarchy changes or something, I can access the key without difficulty. What's the best way for me to make this Key available from within the event handler?

A: 

One potential way is to add an extension method to the checkbox, which finds the TreeNode for you, it could be implemented as some loop which recursively searches the parents until the TreeNode is found.

That way you just call selector.FindTreeNode(), of course this would fail on any checkbox called outside of your structure.

Tetraneutron
I thought about that, but I'm looking for something more generic... something I could use as a best practice. I also thought of doing an extension method like selector.FindParent(typeof(TreeNode)), but it still seems like there must be a better way.
StriplingWarrior
A: 

The best way is to create your own event arguments class that inherits from EventArgs and expose it as a property there. Since you're using a custom or third-party control, I don't have any advice on how to set the property on the event args. A custom events args would look like this:

public class TreeNodeCheckedChangedEventArgs : EventArgs
{
    TreeNodeCheckedChangedEventArgs(int nodeKey)
    {
        NodeKey = nodeKey;
    }

    int NodeKey { get; private set; }

}
Jamie Ide
I'm using a custom control, so I can add to it if necessary. Is there any way to indicate in my ASP.NET markup that the checkbox's OnCheckedChanged event should pass this specialized EventArgs class, or would I have to create my own version of Checkbox as well?
StriplingWarrior
A: 

You can set the value attribute on the checkbox

<asp:CheckBox ID="DemogSelector" runat="server" oncheckedchanged="DemogSelector_CheckedChanged" AutoPostBack="true" value='<%#DataBinder.Eval(Container.DataItem, "Id") %>' />

And retrieve server side

string value = ((CheckBox)sender).Attributes["value"];
Jon
+1  A: 

Best way is to add a custom attribute to your checkbox

<asp:CheckBox ID="DemogSelector" runat="server" oncheckedchanged="DemogSelector_CheckedChanged" AutoPostBack="true" key='<%# Eval("Id") %>'/>

And then access it using

string key = (sender as CheckBox).Attributes["key"];
Hemanshu Bhojak
This is more like what I was looking for. I'll make sure it works, and mark it as the correct response. Jon's answer looks like the same thing, but it looks like you posted first. :-)
StriplingWarrior
A: 

I´m using kind of a similar solution as others, adding my code if it helps:

In markup:

    <ItemTemplate>
        <input type="checkbox" 
          value="<%# Container.DataItemIndex %>" name="CheckedItems" />
    </ItemTemplate>

And in eventhandler:

string checkedItemRowIds = Request.Form["CheckedItems"];
Johan Leino
This isn't quite what I'm looking for, but it could be useful in other circumstances. How does this handle the fact that there will be multiple instances of CheckedItems on the page? Does checkedItemRowIds end up with a comma-separated list or something? You understand that whatever is in the ItemTemplate will be repeated many times, right?
StriplingWarrior