DataGridView with databound combobox

G

Guest

1) I have a DataGridView with edit capability.
But in some columns I want to limit the input with a DropDownList.
There is no inbuilt column for DropDownLists so I intended to add one myself.
I thought the TemplateField would be a good candidate so I added a
DropDownList in the EditItemTemplate and a Literal in the ItemTemplate, but
then I was kind of lost ....
It would be convenient to use the DataGridView for all other fields but
maybe it will not work?

2) Is there a way to Format the value in the normal Show/Edit fields? I have
a date column that looks strange with all "extra time details".
 
G

Guest

Hi Jakob,

1) For the dropdownlist within a GridView, you can add within the
EditItemTemplate a dropdownlist that retrieves its values based on a
datasource object. The dropdownlist can be updated using the one-way
databinding (using Eval) but in order for it to update the datasource you
would have to write code while consuming the GridVeiw.RowUpdating event. I
have a sample that implements this strategy albeit using a FormView. You may
look at its source code and adapt it for the GridView

http://www.webswapp.com/codesamples/aspnet20/dependentlists/default.aspx

2) As for your second question, if you have a DataFormatString applied to a
BoundField you can set the ApplyFormatInEditMode to true.

http://msdn2.microsoft.com/en-us/li....boundfield.applyformatineditmode(VS.80).aspx
 
G

Guest

1) Looks interesting. I will try to apply it to my application tomorrow.
2) Perfect!

Thanks!
 
G

Guest

It is a bit different when using a GridView .....
This is what I came up with:

<asp:GridView ID="grdActivity" runat="server"
AutoGenerateColumns="False" DataSourceID="objActivities">
<Columns>
<asp:BoundField DataField="ActivityDate"
HeaderText="ActivityDate"/>
<asp:TemplateField HeaderText="ActivityTime">
<EditItemTemplate>
<asp:DropDownList ID="cboActivityTime"
runat="server"></asp:DropDownList>
</EditItemTemplate>
<ItemTemplate>
<asp:Literal ID="litActivityTime"
runat="server"></asp:Literal>
</ItemTemplate>
</asp:TemplateField>
<asp:CommandField ShowDeleteButton="True"
ShowEditButton="True" />
</Columns>
</asp:GridView>



Protected Sub grdActivity_RowEditing(ByVal sender As Object, ByVal e As
System.Web.UI.WebControls.GridViewEditEventArgs) Handles
grdActivity.RowEditing

'Get hold of combobox
Dim row As GridViewRow = DirectCast(sender,
GridView).Rows(e.NewEditIndex)
Dim cbo As DropDownList =
DirectCast(row.FindControl("cboActivityTime"), DropDownList)

'Load the combobox
cbo.DataSource = GetAvailableTimes.DefaultView
cbo.DataValueField = "Time"
cbo.DataTextField = "TimeString"
cbo.DataBind()
End Sub

Protected Sub grdActivity_RowUpdating(ByVal sender As Object, ByVal e As
System.Web.UI.WebControls.GridViewUpdateEventArgs) Handles
grdActivity.RowUpdating

'Get hold of combobox
Dim row As GridViewRow = DirectCast(sender,
GridView).Rows(e.NewEditIndex)
Dim cbo As DropDownList =
DirectCast(row.FindControl("cboActivityTime"), DropDownList)

'Set the New value of the object
e.NewValues("ActivityTime") = cbo.SelectedValue

'Accept the value
e.Cancel = False
End Sub


The first problem is that the FindControl will not find the DropDownList,
probably because it is placed inside a TemplateField.
 
G

Guest

Thanks Phillip, I appreciate your effort!

1) I tried hard to get this working but one remaining stumblingblock is this
line:

<asp:DropDownList ID="cboActivityTime" runat="server"
DataSourceID="objTimes" DataValueField="TimeShow" DataTextField="TimeShow"
SelectedValue='<%# Bind("ActivityTime") %>' ></asp:DropDownList>

It will cause this error:
"'cboActivityTime' has a SelectedValue which is invalid because it does not
exist in the list of items.
Parameter name: value"

Possible workaoround?
Your solution obviously works. What is the difference? My ObjectDatasource
retrieves a DataView, will that be a problem?


2) And I am still VERY eager to manipulate the DropDownList in code behind
(Load, set SelectedValue, etc). I am much more used to plain code than these
ObjectSource objects, and find it more flexible.

In the GridView RowEditing Event I can easily get hold of the Literal
control of the TemplateField. Is it impossible to get hold of the
DropDownList control in a similar way?

<asp:TemplateField HeaderText="ActivityTime">
<ItemTemplate>
<asp:Literal ID="litActivityTime" runat="server"
Text='<%# Eval("ActivityTime") %>'></asp:Literal>
</ItemTemplate>
<EditItemTemplate>
<asp:ObjectDataSource ID="objTimes" runat="server"
TypeName="SKF.BusinessLogic.StaticInfo"
SelectMethod="GetNormalTimes"
DataObjectTypeName="SKF.BusinessLogic.StaticInfo"></asp:ObjectDataSource>
<asp:DropDownList ID="cboActivityTime" runat="server"
DataSourceID="objTimes" DataValueField="TimeShow" DataTextField="TimeShow"
SelectedValue='<%# Bind("ActivityTime") %>' ></asp:DropDownList>
</EditItemTemplate>
</asp:TemplateField>


Protected Sub grdActivity_RowEditing(ByVal sender As Object, ByVal e As
System.Web.UI.WebControls.GridViewEditEventArgs) Handles
grdActivity.RowEditing
Dim grd As GridView
Dim row As GridViewRow
Dim lit As New Literal
Dim cbo As DropDownList

grd = DirectCast(sender, GridView)
row = DirectCast(sender, GridView).Rows(e.NewEditIndex)
lit = DirectCast(row.FindControl("litActivityTime"), Literal)
'cbo = DirectCast(row.FindControl("cboActivityTime"), DropDownList)
End Sub
 
G

Guest

Hello Jakob,

Since you are using Bind (which will set the selected value from the data as
well as save the selected value to data upon update), the dropdownlist must
be populated with all possible values. In your specific code, for example,
if you had a value in the field named “ActivityTime†that is not within the
set of values for “TimeShow†then you would get that error. It can also
happen if your datatable schema was created to allow nulls in ActivityTime.

The solutions are:
1- if the problem is happening due to Null values in AcitvityTime then you
can declare the dropdownlist like this:

<asp:DropDownList ID="cboActivityTime" runat="server"
AppendDataBoundItems=â€trueâ€
DataSourceID="objTimes" DataValueField="TimeShow" DataTextField="TimeShow"
SelectedValue='<%# Bind("ActivityTime") %>' ></asp:DropDownList>

http://msdn2.microsoft.com/en-us/li....listcontrol.appenddatabounditems(VS.80).aspx

2- if the problem is happening due to illegal values saved in “ActivityTimeâ€
(that are not part of the set of values for TimeShow) then you can:

a. fix the data

b. create a UNION query within the objTimes that would bring not only the
values from the “TimeShow†but also any values in “ActivityTime†that is not
included

c. handle it on the level of the user interface like I did on my sample
where I removed the Bind statement from the DropDownList and replaced with
code within the dropdownlist.DataBound event, e.g.

Protected Sub cboAcitvityTime_DataBound(ByVal sender As Object, ByVal e As
EventArgs)
Dim ddl As DropDownList = CType(sender, DropDownList)
Dim gvr As GridViewRow = CType(ddl.NamingContainer, GridViewRow)
If Not gvr.DataItem Is Nothing Then
Dim strTimeShow As String = CType(gvr.DataItem, DataRowView)("
TimeShow")
'be careful of the possibility that the value saved on the
'database does not exist in the valid selections that are
displayed
'on the list
ddl.ClearSelection()
Dim li As ListItem = ddl.Items.FindByValue(strTimeShow)
If Not li Is Nothing Then li.Selected = True
End If

In which case you would also have to save the selected value upon update by
consuming the GridViewRowUpdating, like this:

Protected Sub grdActivity_RowUpdating (ByVal sender As Object, ByVal e As
GridViewUpdateEventArgs)
Dim strTimeShow As String = CType(CType(sender,
GridViewRow).FindControl("cboActivityTime"), DropDownList).SelectedValue
e.NewValues("ActivityTime") = strTimeShow
e.Cancel = False
End Sub


Regarding your question on how to find the dropdownlist within the
GridViewRow while handling the RowEditing event…

The RowEditing event is raised when a row's Edit button is clicked, but
before the GridView control enters edit mode.
http://msdn2.microsoft.com/en-us/library/system.web.ui.webcontrols.gridview.rowediting(VS.80).aspx

Which means that during this event processing the dropdownlist has not yet
been rendered. You can find that dropdownlist after the edit is complete
and the user pressed on the update command which will trigger the RowUpdating
event.
 
G

Guest

Sorry I didn't answer before, but for some reason I was not notified of your
reply.

I am ashamed to tell you but I found out today(!) that all the problem was
caused by a totally different reason: the combobox was loaded with times of
the format "11.00" but the database contained times formatted as "11:00", and
I didn't notice!!!

As for combobox not being reachable in the RowEditing event, it makes sense :)

It all works by now and I am happy, Thanks!
 
G

Guest

Sorry I didn't answer before, but for some reason I was not notified of your
reply and didn't see it until today.

I am ashamed to confess that the main problem had a totally different
reason: the combobox was loaded with values on the form "11.00" but the
database held values on the form "11:00" and I was totally blind for the
difference all the time ... !

I understand that the combobox is not created yet in the RowEditing event,
it makes sense :)

It all works by now so I am all happy again, Thanks!
 
G

Guest

Thanks Jakob for the feed-back. I am glad you managed to get the
dropdownlist/gridview working.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top