views:

293

answers:

2

I created a row (header row) in a gridview with a dropdownlist among other input controls. I also put a button on that row (fltbttn-see below). I created an addhandler for the button called fltbttn_Click. I want gain access to my dropdownlist (ddlscantype) using findcontrol but how can I get to the header row where the filter controls exist?

   Dim fltbttn As New ImageButton
   fltbttn.ImageUrl = "\images\bttnFilter.gif"
   AddHandler fltbttn.Click, AddressOf fltbttn_Click
   Dim cell As New TableCell
   Dim row As New GridViewRow(-1, -1, DataControlRowType.Header, DataControlRowState.Normal)
   Dim ddlscantype As New DropDownList
    AddHandler ddlscantype.SelectedIndexChanged, AddressOf ddlscantype_Changed
    ddlscantype.DataSource = SqlDataSource2
    ddlscantype.DataValueField = "value"
    ddlscantype.DataTextField = "name"
    ddlscantype.DataBind()
   row.Cells.Add(cell)
   cell.Controls.Add(ddlscantype)

MARKUP

<asp:UpdatePanel ID="UpdatePanel1" runat="server">
    <ContentTemplate >
        <asp:GridView ID="GridView1" runat="server" AllowPaging="True" 
            AutoGenerateColumns="False" BackColor="White" BorderColor="#E7E7FF" 
            BorderStyle="None" BorderWidth="1px" CellPadding="3" 
            DataSourceID="SqlDataSource1" Font-Names="Estrangelo Edessa" Font-Size="Small" 
            ShowFooter="True"
            Caption = '<table border="" width="100%" cellpadding="3" cellspacing="0" bgcolor="#4A3C8C"><tr><td style = "font-size:X-large;font-family:Arial CE;color:White"><b>Receiving Error Log</u></td></tr></table>' >
            <RowStyle BackColor="#E7E7FF" ForeColor="#4A3C8C" />
            <Columns>
                <asp:BoundField DataField="scan" HeaderText="Scan" SortExpression="scan" />
                <asp:BoundField DataField="ScanType" HeaderText="ScanType" ReadOnly="True" 
                    SortExpression="ScanType" />
                <asp:BoundField DataField="Vendor" HeaderText="ht" ReadOnly="True" 
                    SortExpression="ht" />
                <asp:BoundField DataField="Name" HeaderText="ht2" ReadOnly="True" 
                    SortExpression="ht2" />
            </Columns>
            //footer style and pager style blah blah blah goes here.
            </ContentTemplate> 
    </asp:UpdatePanel>
    <ajaxToolkit:UpdatePanelAnimationExtender ID="upae" BehaviorID ="animation" runat="server" TargetControlID = "UpdatePanel1" >
         <Animations >
            <OnUpdating>
                <Parallel duration="0">
                  <ScriptAction Script="onUpdating();" />
                </Parallel>
            </OnUpdating>
            <OnUpdated>
                <Parallel duration="0">
                <ScriptAction Script="onUpdated();" /> 
                </Parallel>
            </OnUpdated>    
         </Animations>
+1  A: 

Well the first thing that jumps out at me is that you've dynamically created your DropDownList...but you've created it within a function.

You have to keep in mind that variables/objects have scope. The scope of your DropDownList is within the function that you've declared it. This means that it will be added to the page and rendered but once it's finished, it's destroyed. When the user causes a postback to the server, the DropDownList no longer exists...and so the event will never fire.

You have to give the DropDownList a scope of the whole page. Declare it at the page level.

The other thing you have to keep in mind when using dynamic controls is the ASP Page Life Cycle.

The page is posted to the server...

The server creates all of the objects needed to do server calculations in the Page Init Event....

Right after the page Init Event the ViewState is loaded for the page...the ViewState is used to determine what event(s) caused the postback to happen.

If your DropDownList does not exist when the ViewState is loaded for the control, then the event will be lost and your code will not handle it.

My recommendation for you is to try to avoid using dynamic controls. Sometimes you Have to use them...but they are not easy to use.

I wrote a little article on using dynamic ASP.NET controls that may help you better understand.

-Frinny

Frinavale
The only problem with creating the controls in page init is that none of the rows in the Gridview exist and I would get index out of range on this line :GridView1.Rows(0).Parent.Controls.AddAt(0, row)that's where i add the row
Eric
Yeah that's why I recommended staying away from dynamic controls. Well, you could try creating the dynamic DropDownList in the PageInit event and then populating later in the cycle....
Frinavale
if i don't use dynamic controls, what would be my other options? I just need to add a row that contains filter controls to filter the data in the gridview.
Eric
Have you ever used the ITemplate interface before? This interface lets you dynamically create templates to use with your GridView (and other controls that use templates). You could create a template to use with your Header row. In this template you would dynamically create the DropDownList and Button. Then in your PageInit event you'd apply the template to the GridView.
Frinavale
You know, there might be a better way to do this....something not so dynamic. Let me see if you can do this in the ASP code....
Frinavale
Ok, sorry it's been a while since I've used a GridView. You can't actually do anything with it in the ASP code (there's no way to apply a HeaderTemplate). It's looking more and more like you're going to have to use a dynamic solution. I think that you're going to have to add you columns dynamically too...
Frinavale
yeah...i thought so. I would think that asp.net would recognize the importance of fitering a gridview and made some type of control or method to do so....Thanks for your help. +1
Eric
If you have any problems using dynamic templates let me know and I'll see if I can help you. I had a hell of a time with them when I was first learning how to use them...especially with handling event generated by the dynamic controls within the dynamic templates in the Page code.
Frinavale
This got me the control I needed. I just have to take care of postback issues nowDim cell As TableCell = DirectCast(sender.parent, TableCell) Dim ddlscantype As DropDownList = DirectCast(cell.Controls(2), DropDownList)
Eric
+1  A: 

Why don't you use the TemplateField type for one of your datacolumns, then use a templated header?

for example:

<asp:TemplateField>
    <ItemTemplate>
    <%# Eval("Vendor") %>
    </ItemTemplate>
    <HeaderTemplate>
    <asp:DropDownList ID="ddlscantype" runat="server" DataSourceID="SqlDataSource2" DataTextField="name" DataValueField="id" OnSelectedIndexChanged="YourCallbackMethod" />        
    </HeaderTemplate>
</asp:TemplateField>

This should allow you to fit the drop down inside of your header row, as well as not requiring any dynamic control creation.

Don't forget to wire up your event here...

jkelley
To build on what jkelley said then you can use FindControl on the GridView.HeaderRow property in your event handler.
ewrankin
this will put the dropdownlist where my column names are. I want them above the actual header.
Eric
so fully above the header row? or in the header row, but above the text?
jkelley
Ahh this is what I was looking for earlier when I said "there must be an easier way to do this". This should work perfectly for your needs!
Frinavale
So...if you want to add them in a full row above the header row, you could simply edit my above post to include the dropdownlist as shown, then a <br /> then the desired header text. This should allow you to get both your header text as well as the filter, though it does sacrifice having a separate row for each.You can also go ahead and create a div directly above the entire grid view, then use CSS to nest it nicely over the table...may even end up requiring less characters!
jkelley