Welcome to AspAdvice Sign in | Join | Help

.Net Discoveries

An attempt to pass along some answers I have discovered in my .Net coding.
Targeting a Control in the EmptyDataTemplate

Prologue

Recently I've been working on our new corporate website. Some of my previous posts have talked about a web service that I created to use on the new website. When I consume the web service, I've been creating a table and putting the information into the table and then binding it to a GridView. Since our web service could quite feasible dish up an empty result set, it sounds reasonable for us to use the EmptyDataTemplate to display something when there is no data.

Problem

The EmptyDataTemplate would allow us to manually enter the data that we want displayed when no data is present, however I prefer to allow messages like this to be easily customizable (I'll be using it in more than one place), so I prefer to create an entry that I can pull from the web.config. Unfortunately, you can't just target the control directly. I've run into this problem before; the control doesn't really exist until it is created, so targeting it directly won't always work. Luckily I've found a way around this that works nicely.

Solution

To get started, let's start by setting up our page. Create a new page, and call it EmptyDataTemplateTest.aspx. Switch over to design view and drop a GridView control onto the page, and name it gvwTest. Now switch over to source view and let's layout our control.

We'll make it easy, we'll instruct the GridView to generate it's own columns based on our DataSource, so really all we need to do is come up with the EmptyDataTemplate. Inside our EmptyDataTemplate, we want to create a label that we can push our dynamic text to, so our code should look like this:

<asp:gridview ID="gvwTest" runat="server" AutoGenerateColumns="True">
   <EmptyDataTemplate>
      <asp:Label ID="lblEmptyText" runat="server" />
   </EmptyDataTemplate>
</asp:gridview>

Ok, the front-end is all setup, let's setup the code-behind. Open the code-behind file and let's add some code to create a table, populate some data to it and then bind it to our GridView. Let's create a helper function to create a DataTable and create a couple entries in it. Start by importing the System.Data namespace in your project and create a new function as follows:

Public Function CreateDataSource(ByVal bEmpty As Boolean) As DataTable
    Dim dt As New DataTable()

    dt.Columns.Add(New DataColumn("FirstName", GetType(String)))
    dt.Columns.Add(New DataColumn("LastName", GetType(String)))

    If bEmpty = False Then
        Dim dr As DataRow
        dr = dt.NewRow()
        dr("FirstName") = "Sally"
        dr("LastName") = "Smith"
        dt.Rows.Add(dr)
        dr = dt.NewRow()
        dr("FirstName") = "John"
        dr("LastName") = "Doe"
        dt.Rows.Add(dr)
    End If

    Return dt
End Function

Basically, we create a DataTable, add 2 columns (FirstName and Last Name) and then based on whether we requested an empty DataSet (so it's easy to simulate empty data), we either do or don't create two rows and add them to the table. Then we return the table.

Finally to finish our setup, add the following to your Page_Load event:

gvwTest.DataSource = CreateDataSource(False)
gvwTest.DataBind()

This will assign and the bind our DataSource. Run your application and see how it works. If it works properly you should have a table with two entries. Now, let's try to assign a message to the label in our EmptyDataTemplate. Notice that it doesn't appear in our object drop down list (at the top), so how do we assign to it? Well, we have to wait for it to be loaded and the grab it on creation and add our text. Go back to your HTML code and modify your Label definition in your EmptyDataTemplate as follows:

<asp:Label ID="lblEmptyText" runat="server" OnLoad="GetEmptyText" />

Basically we're letting the control know that we want it to run a subroutine when it loads, we can't just use it's event handler like we would a normal control because it doesn't exist unless we actually DON'T have any data. (NOTE: Do NOT put a () after your GetEmptyText declaration, if you do you'll get a runtime error later about not specifying parameters - just skip the parentheses). Now let's go back to our code-behind and create the subroutine to go with it. Create a subroutine as follows (Note: this routine MUST be public or it will not work):

Public Sub GetEmptyText()
   lblEmptyText.Text = "Empty Recordset"
End Sub

Notice that we get a compile error because our label doesn't exist. So how do we get around this? Well, technically our Subroutine is the event handler for the load event SO, we can add parameters that match that of any label's load event, so let's modify our Subroutine's declaration line to be:

Public Sub GetEmptyText(ByVal sender As Object, _
    ByVal e As System.EventArgs)

So what exactly does our new declaration get us that we didn't have before? The sender object. Now you might think we need to use a FindControl() command and find our label in all the page's mess, and you might be able to do this, but there is an easier way. The sender object is really our label control in disguise, we just need to pull it together and make our change. Modify the contents of your subroutine as follows:

Dim lblEmptyText As Label = CType(sender, Label)
lblEmptyText.text = "Empty Recordset"

We created a label object and cast our sender to it and then we can access it's properties. Now when you run your application with an empty Recordset, you get your customized empty recordset message.

Epilogue

This is an easy way to enable yourself to make your message easily manageable. I use the same message in about 4 different places so it made sense to have a repository (mine's in the web.config) to pull this message from. Now I don't have to remember all the places where it is and do all the changes and hope I don't break anything, I simply change the web.config and re-upload it.

Posted: Friday, August 22, 2008 2:52 PM by Yougotiger

Comments

PJDJ said:

Nice workaround. I've read elsewhere that you can find the parent like this: GridView1.Controls[0].Controls[0].FindControl("txtControl")
# October 21, 2008 6:17 PM

Yougotiger said:

Thanks, I appreciate the good feedback...

# October 21, 2008 6:27 PM

Juan S said:

Is it possible to use this technique to change the header of the gridview on runtime (multilingual application)? Anyways, excellent presentation Thank you
# March 27, 2009 6:10 PM

Yougotiger said:

Juan S,

You don't need to do anything special to target the header text in a GridView. It's a property of the column, you can target it like this:

gvMyGridView.Columns(0).HeaderText = "xyz"

# March 27, 2009 6:58 PM

Juan S said:

I implemented this solution for the empty gridview. It works, but when I click on the headers to sort I get the message of empty gridview. Press the button that set the gridview and the data shows up but now sorted as requested sorted. If number or rows larger than viewable, when I press the page number to move, the empty message shows as well. It looks like any control inside the gridview area when requested gives presedence to the emptydatatemplate even when there is data. Any ideas?
# March 28, 2009 10:01 AM

Yougotiger said:

Juan,

I'm not sure I entirely understand your question. I can't replicate the issue. If you can send me your code, or I'll take a look at it and see what I can come up with.

# March 30, 2009 7:16 PM

ricpue@gmail.com said:

Nice!!! thanks for your post.
# August 27, 2009 1:55 PM

Phil said:

Yougottiger!! I have searched high and low for this!!! I stumbled across this post after deciding I would be stuck with a static message in my empty data template... Good job and Thanks!!!
# September 17, 2009 7:54 AM

Jay Harvey said:

Thanks for sharing this. It helped me solve a similar problem.
# December 10, 2009 12:36 PM

Mike Wilson said:

If you don't have a control in the EmptyDataTemplate - you just have text - you can simply change the text displayed by using gvMyGridview.EmptyDataText = "Your empty recordset message" after binding your data (and, obviously, testing for an empty dataset).
# February 5, 2010 7:16 AM

Brad said:

@Mike Wilson - Thank you for suggesting this simple solution. Saved me lots of time. I had data pulling from a query string and no way of getting that into my EmptyDataTemplate. A lot easier to do with your method. Thanks again.
# February 26, 2010 4:13 PM
Leave a Comment

(required) 

(required) 

(optional)

(required) 

Enter the code you see below

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS