|
Now, let's do one final thing. Fans are extremely loyal to their favorite band members, so let's provide a way for them to click on their favorite member's name to display only entries that they've created.
First, we need a method of selecting the author whose entries we want to view. Let's create a set of LinkButton controls to do this. Each button will represent a different band member. When the member's button is clicked, only that member's entries will be displayed. Add six LinkButton controls above the DataGrid, all in a row, one after the other. We'll have a button for each band member, plus one to display all entries. Here are the properties for the buttons:
Control | Properties | Values |
---|---|---|
btnNoFilter | CommandName | Filter |
CommandArgument | NoFilter | |
Command (from events tab) | FilterButton_Command | |
Text | All Entries | |
btnAl | CommandName | Filter |
CommandArgument | Al | |
onCommand | FilterButton_Command | |
Text | Al | |
btnColt | CommandName | Filter |
CommandArgument | Colt | |
onCommand | FilterButton_Command | |
Text | Colt | |
btnDave | CommandName | Filter |
CommandArgument | Dave | |
onCommand | FilterButton_Command | |
Text | Dave | |
btnJohn | CommandName | Filter |
CommandArgument | John | |
onCommand | FilterButton_Command | |
Text | John | |
btnJames | CommandName | Filter |
CommandArgument | James | |
onCommand | FilterButton_Command | |
Text | James |
All buttons will call the same Command() method on the page. To know what to filter by, we'll use the CommandArgument property.
Add a FilterValue property to the page:
Property FilterValue() As String Get Dim o As Object = ViewState("FilterValue") If o Is Nothing Then Return "NoFilter" End If Return CStr(o) End Get Set(ByVal Value As String) ViewState("FilterValue") = Value End Set End Property
This property will store the filter value we pass via the CommandArgument property on the link button. In turn, we'll use this property when we bind the data in the DataGrid.
Next, we need the event handler for when a LinkButton is clicked. The command event is fired when the button is clicked. Here's our handler:
Sub FilterButton_Command(sender as object, e as CommandEventArgs) FilterValue = e.CommandArgument BindGrid() End Sub
This event passes the object that was clicked and the CommandEventArgs property. The latter contains the command name and command argument that was specified for the control that was clicked. Note that in this case, we only have one command on the page, so we don't need to put any conditional logic to check for the command name. We simply utilize the command argument to set the FilterValue. Then we reload the grid.
Now, we need to modify the BindGrid() subroutine to filter the data when appropriate. We have two options: we can change the CAM.TourDiaryDB class to allow passing of the filter value, or we can filter after the dataset has been returned to our page. There's no right or wrong answer. If you have a lot of data, it's often more efficient to let the database do the filtering so that you're not passing so much data from the database to the calling object. On the other hand, a lot of times in a real programming environment you may not have the option of changing the data-tier classes, so you have to work around their limitations. Or, you might be caching the data on the web server so that you don't have to do database accesses each time you display data on the page. In this case, I'm going to filter after the dataset has been returned.
Unfortunately, the dataset doesn't allow itself to be filtered directly. Instead, you need to get the data view you want to filter on, and then perform the filter itself. Here's new BindGrid() code:
Sub BindGrid() Dim TDDB As New TourDiaryDB() Dim dv As DataView dv = TDDB.ReadTourDiaryEntries(SortField).Tables(0).DefaultView If FilterValue <> "NoFilter" Then dv.Rowfilter = "author = '" & FilterValue & "'" Else dv.RowFilter = "" End If DataGrid1.DataSource = dv DataGrid1.DataBind() End Sub
That's our code sorted out. Now, when you recompile and run the page, and when you click on the John LinkButton, say, you'll see only his entries, like the following:
When you click on All Entries, you'll clear the RowFilter and see all of the entries again.
One of the most important points about this example is that we have five link buttons, but only one event procedure. In previous examples we've had an event procedure for each button, but that would be wasteful here, since we want to perform the same action from each button. This is possible because we set the onCommand event property for all of the buttons to the same event procedure, so the same procedure will run whichever button we click. The second parameter of the event procedure contains specific details of which button was pressed – ASP.NET automatically passes this information to us, and since we set the CommandArgument property for each button (to the name of the band member), we can use this in the event procedure:
Sub FilterButton_Command(sender as object, e as CommandEventArgs) FilterValue = e.CommandArgument BindGrid() End Sub
Here, we just extract the CommandArgument and use that as the value for the filter. We can then bind the grid to the data.
In the BindGrid() routine, we take that filter value, and we use it to show only those records. We can do that with a DataView, which is a sortable, filterable view of the data. Each table in a DataSet has a DefaultView, which is the unfiltered view of the data – normally we bind directly to this default view, but we want to filter the data so we create a DataView variable, and set this to the DefaultView of the first table in the DataSet (there is only one table):
dv = TDDB.ReadTourDiaryEntries(SortField).Tables(0).DefaultView
If the FilterValue is NoFilter, we clear the DataView's RowFilter by setting it to empty as well. If it's not empty, then we build the filter criteria string, which in this case means searching the Author field for records that have the same name as FilterValue itself:
If FilterValue <> "NoFilter" Then dv.Rowfilter = "author = '" & FilterValue & "'" Else dv.RowFilter = "" End If
Finally, we set the data source to this filtered DataView:
DataGrid1.DataSource = dv
|