About

I'm Mike Pope. I live in the Seattle area. I've been a technical writer and editor for over 35 years. I'm interested in software, language, music, movies, books, motorcycles, travel, and ... well, lots of stuff.

Read more ...

Blog Search


(Supports AND)

Feed

Subscribe to the RSS feed for this blog.

See this post for info on full versus truncated feeds.

Quote

When the Sun-Times appointed me film critic, I hadn't taken a single film course. One of the reasons I started teaching was to teach myself.

Roger Ebert



Navigation





<January 2025>
SMTWTFS
2930311234
567891011
12131415161718
19202122232425
2627282930311
2345678

Categories

  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  

Contact Me

Email me

Blog Statistics

Dates
First entry - 6/27/2003
Most recent entry - 9/4/2024

Totals
Posts - 2655
Comments - 2677
Hits - 2,721,266

Averages
Entries/day - 0.34
Comments/entry - 1.01
Hits/day - 346

Updated every 30 minutes. Last: 10:06 PM Pacific


  07:48 PM

I've been messing with cascading drop-down lists in the FormView control. In a comment, someone asked if the same thing can be done in a GridView control in edit mode. Yes. The overall approach is pretty much the same. There are a few details that differ because we're in a GridView row.

To review, when you're working with cascading DropDownList controls, you need to perform these tasks:
  • Populate each of the DropDownList controls.
  • Pre-select the appropriate value in each list to match what's currently in the data.
  • When the user selects a new value in the master dropdown, repopulate the detail dropdown with a new set of dependent values.
  • When the row is saved, read the values from the dropdown lists and use them to set the values of parameters that will be passed to the database query that updates the database.
Update Some folks have requested info about the schema of the tables involved in this exercise. Here you go:
Customers
CustomerID
Name
Manufacturer
Model
Manufacturers
Manufacturers
Models
ModelID
Manufacturer
Model

As I say, you can do this in the GridView control in a way similar, but not identical, to how you do it in FormView. Let's say you have a grid that looks like this in normal mode (ItemTemplate):



And like this in edit mode (EditItemTemplate):



When you configure the GridView control, you have to convert the columns for Manufacturer and Model from BoundField columns (default) to TemplateField columns. A template column gives you a way to design the column contents freeform. Then you edit the columns. For the ItemTemplate of both columns, you add a Label control and data-bind it using the Bind (or even just the Eval) method. Here's an example of the Manufacturer column showing just the ItemTemplate element:
<asp:TemplateField HeaderText="Manufacturer" 
SortExpression="Manufacturer">
<ItemTemplate>
<asp:Label ID="Label1"
runat="server"
Text='<%# Bind("Manufacturer") %>'>
</asp:Label>
</ItemTemplate>


[...]
The EditItemTemplate is where the fun happens. As with the FormView example from before, the template contains both the drop-down list and the data source control for that list. Here's the markup for the EditItemTemplate element for the Manufacturer column:
<EditItemTemplate>
<asp:DropDownList
ID="listManufacturers"
runat="server"
DataSourceID="dsManufacturers"
DataTextField="Manufacturer"
DataValueField="ManufacturerID"
autopostback=true
OnSelectedIndexChanged="listManufacturers_SelectedIndexChanged">
</asp:DropDownList>


<asp:AccessDataSource ID="dsManufacturers"
runat="server"
DataFile="~/App_Data/Cars.mdb"
SelectCommand="SELECT [ManufacturerID], [Manufacturer] FROM [Manufacturers]">
</asp:AccessDataSource>
</EditItemTemplate>
Notice that the AutoPostBack property of the DropDownList control is true. As soon as users select an item from the list, we want to refresh the dependent drop-down list.

Here's the Model column (I wrapped the query for readability):
<asp:TemplateField HeaderText="Model" SortExpression="ModelName">
<ItemTemplate>
<asp:Label ID="Label2"
runat="server"
Text='<%# Bind("ModelName") %>'>
</asp:Label>
</ItemTemplate>


<EditItemTemplate>
<asp:DropDownList ID="listModels"
runat="server"
DataSourceID="dsModelsByManufacturer"
DataTextField="ModelName"
DataValueField="ModelID" />


<asp:AccessDataSource
ID="dsModelsByManufacturer"
runat="server"
DataFile="~/App_Data/Cars.mdb"
SelectCommand="SELECT [ModelID], [ModelName] FROM [Models] WHERE
([ManufacturerID] = ?)">
<SelectParameters>
<asp:Parameter Name="ManufacturerID" />
</SelectParameters>
</asp:AccessDataSource>


</EditItemTemplate>
</asp:TemplateField>
The Model column also contains a data source control. The query is parameterized; the ManufacturerID value will be supplied at run time.

And now some code. First, we want to populate the controls and preselect the current item. The right time to do that is when the GridView control is doing its data-binding thing.
Protected Sub GridView1_RowDataBound(ByVal sender As Object, ByVal e _
As System.Web.UI.WebControls.GridViewRowEventArgs)
If (e.Row.RowState And DataControlRowState.Edit) = _
DataControlRowState.Edit Then
Dim dv As System.Data.DataRowView = e.Row.DataItem

' Preselect correct value in Manufacturers list
Dim listManufacturers As DropDownList = _
e.Row.FindControl("listManufacturers")
listManufacturers.SelectedValue = dv("ManufacturerID")


' Databind list of models in dependent drop-down list
Dim listModels As DropDownList = _
e.Row.FindControl("listModels")
Dim dsc As AccessDataSource = _
e.Row.FindControl("dsModelsByManufacturer")
dsc.SelectParameters("ManufacturerID").DefaultValue = _
dv("ManufacturerID")
listModels.DataBind()
listModels.SelectedValue = dv("ModelID")
End If
End Sub
(Some ugly line-continuations in there, sorry.)

The drop-down lists are displayed only in edit mode, so the code first tests e.Row.RowState. That guy threw me for a while -- turns out that it's a bitfield, so you test it by ANDing it. Having established that edit mode is active, the code gets the current manufacturer ID from the current data item (typed as DataRowView) and selects that value. Then it uses the manufacturer ID to set the parameter value for the query in the model data source, binds the model drop-down list, and then preselects the current model.

Wow, this is getting long. To be continued ...

Update The next blog entry finishes this discussion and includes a link to the source code for this page.

[categories]  

[16] |