So I have some GridView. When you edit a row, a particular column changes from a label to a DropDownList. The content of this drop down is populated via some SQL data source.
The user may make a selection choice and click "Update".
How can I actually get at the SelectedValue property of the drop down?
I thought this would work:
<asp:GridView ... >
<Columns>
...
<EditItemTemplate>
<asp:DropDownList ID="ServiceCategoriesGvDropDown" AutoPostBack="True" .../>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ... />
</ItemTemplate>
</asp:TemplateField>
...
</Columns>
</asp:GridView>
And then wire it up with a ControlParameter in my SqlDataSource:
<UpdateParameters>
...
<asp:ControlParameter ControlID="ServiceCategoriesGvDropDown" PropertyName="SelectedValue" ... />
</UpdateParameters>
However, I get the following exception:
System.InvalidOperationException: Could not find control 'ServiceCategoriesGvDropDown' in ControlParameter 'ServiceCategoriesID'.
So clearly my drop down doesn't get found. Perhaps it's been destroyed by this point?
try this in the updating event of the grid.
protected void YourGrid_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
DropDownList ddl= (DropDownList )YourGrid.Rows[e.RowIndex].FindControl("ddlId");
string selectedvalue=ddl.selectedvalue;
//Your update code goes here
}
What I think you need to do is:
Attach a SelectedIndexChange event to the DropDownlist on your Gridview
Grab the SelectedValue on that event.
Grab a reference to your DataSource's UpdateParameters and populate the respective parameter programmatically with the SelectedValue.
Call your DataSource's Update method.
You can try doing this:
assuming the ID of the gridview is gridview1
<asp:ControlParameter ControlID="gridview1$ServiceCategoriesGvDropDown" PropertyName="SelectedValue" />
Related
I have a WebForms GridView, where I want to update a BoundField conditionally (or I use a value from a DropDown or I use the text from a Textbox), based on the value from another DropDownList.
<asp:GridView ID="gv_results" runat="server" DataKeyNames="ID_RESULTS" DataSourceID="get_results">
<Columns>
<asp:TemplateField HeaderText="DETAIL" SortExpression="DETAIL">
<EditItemTemplate>
<asp:TextBox ID="tb_detail_edit" runat="server"></asp:TextBox>
<asp:DropDownList ID="dd_detail_edit" runat="server" AutoPostBack="True" DataSourceID="get_detail" DataTextField="DETAIL" DataValueField="DETAIL" ></asp:DropDownList>
</asp:SqlDataSource>
</EditItemTemplate>
<ItemTemplate>
<asp:SqlDataSource runat="server" ID="get_results"
UpdateCommand="UPDATE RESULTS SET [DETAIL] = COALESCE(#DETAIL,#DETAILwelcome)">
<UpdateParameters>
<asp:ControlParameter ControlID="ctl00$MainContent$gv_results$ctl02$dd_detail_edit" PropertyName="SelectedValue" Name="DETAIL" Type="String"></asp:ControlParameter>
<asp:ControlParameter ControlID="ctl00$MainContent$gv_results$ctl02$tb_detail_edit" PropertyName="Text" Name="DETAILwelcome" Type="String"></asp:ControlParameter>
</UpdateParameters>
</asp:SqlDataSource>
Well, I found out in the google's that I have to use the Direct ID in the Control Parameter. And it works...the thing is , the $ctl02 (for example) before the id of the dd_detail_edit, changes, with different rows in the Gridview (so this id works for one row, but maybe for the next it doesn't work.
Is there some workaround for this?
Using only something like $gv_results$dd_detail_edit , doesn't work, I dunno why :S
TIA and Best Regards,
For one thing it looks like you have an open <ItemTemplate> tag without any closing one.
If you check out the .net documentation you can see where they use the regular control IDs, like ControlID = dd_detail_edit.
I do not think you're providing enough details for me to provide a complete answer, but those are a couple of things I noticed.
I have a dropdown list (doc_rvw_sub_recip_list) that is populated with names from tbl_ad_users. tbl_ad_users contains a field titled "domain_user". I would like to populate an asp:hiddenfield (hdn_domain_user) with the "domain_user" based on the selected value in the doc_rvw_sub_recip_list dropdown list. For testing I used a dropdown list (domain_user_ddl) instead of a hidden field, and it works as needed. But I don't know how to get the value into a hidden field as opposed to using a dropdown list.
The following is doc_rvw_sub_recip_list:
<asp:DropDownList ID="doc_rvw_sub_recip_list" runat="server" DataSourceID="sdc_ad_user_list" DataTextField="name" DataValueField="email_address" AppendDataBoundItems="true" AutoPostBack="true"><asp:ListItem Value="">Please Select</asp:ListItem></asp:DropDownList>
The following is the sql data source for domain_user_ddl:
<asp:SqlDataSource ID="sdc_domain_user_ddl" runat="server" ConnectionString='<%$ ConnectionStrings:idrfConnectionString %>' SelectCommand="SELECT [domain_user] FROM [tbl_ad_users] WHERE ([email_address] = #email_address)">
<SelectParameters>
<asp:ControlParameter ControlID="doc_rvw_sub_recip_list" PropertyName="SelectedValue" Name="email_address" Type="String"></asp:ControlParameter>
</SelectParameters>
</asp:SqlDataSource>
The following is domain_user_ddl:
<asp:DropDownList ID="domain_user_ddl" runat="server" DataSourceID="sdc_domain_user_ddl" DataTextField="domain_user" DataValueField="domain_user" AutoPostBack="true"></asp:DropDownList>
How do I get this to work for hdn_domain_user just as it works for domain_user_ddl?
ASPX
Add a OnSelectedIndexChanged event to your dropdown...
<asp:DropDownList ID="doc_rvw_sub_recip_list" runat="server" DataSourceID="sdc_ad_user_list" DataTextField="name" DataValueField="email_address" AppendDataBoundItems="true" AutoPostBack="true" OnSelectedIndexChanged="doc_rvw_sub_recip_list_SelectedIndexChanged"><asp:ListItem Value="">Please Select</asp:ListItem></asp:DropDownList>
Add your hidden field...
<asp:HiddenField runat="server" ID="hdn_domain_user" />
Code Behind
Handle the SelectedIndexChanged event...
protected void doc_rvw_sub_recip_list_SelectedIndexChanged(Object sender, EventArgs e)
{
// Populate the hidden field if the dropdown has a selected value
if (doc_rvw_sub_recip_list.SelectedValue != null)
hdn_domain_user.Value = doc_rvw_sub_recip_list.SelectedValue;
}
I'm using gridview with edit/delete. When the user clicks on "Edit" I need to pass a value from one column (100mPLot) to a datasource that would populate a dropdownlist of another column (SubPlot). This is what I have:
<asp:BoundField DataField="100mPlot" HeaderText="100m plot"
SortExpression="100mPlot" ReadOnly="True" />
<asp:TemplateField HeaderText="SubPlot" SortExpression="SubPlot">
<EditItemTemplate>
<asp:DropDownList ID="DropDownList1" runat="server"
DataSourceID="dsSubPlotNames"
DataTextField="SiteName" DataValueField="SiteID"
SelectedValue='<%# Bind("SiteID") %>'
>
</asp:DropDownList>
<asp:SqlDataSource ID="dsSubPlotNames" runat="server"
ConnectionString="<%$ ConnectionStrings:WERCMTX %>" SelectCommand='exec [339_PPM].usp_SubPlotNames_Select null, #100mPlotName;'
CancelSelectOnNullParameter="False">
<SelectParameters>
<asp:ControlParameter ControlID="GridView1" DefaultValue='<%# Eval("100mPlot") '
Name="100mPlotName" PropertyName="SelectedValue" />
</SelectParameters>
</asp:SqlDataSource>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="Label3" runat="server" Text='<%# Bind("SubPlot") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
Unfortunately, I get this error with the Eval("100mPlot"):
Databinding expressions are only supported on objects that have a DataBinding event. System.Web.UI.WebControls.ControlParameter does not have a DataBinding event.
How do I fix this? Thanks,
EDIT:
I moved it to code behind and handled it in RowDataBound after creating a hidden label tag containing the value of the previous column.
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow && (e.Row.RowState & DataControlRowState.Edit) == DataControlRowState.Edit)
{
Label lbl100mPlot = (Label)e.Row.FindControl("lbl100mPlot");
SqlDataSource dsPlotNames = (SqlDataSource)e.Row.FindControl("dsSubPlotNames");
dsPlotNames.SelectParameters.Clear();
dsPlotNames.SelectParameters.Add("100mPlotSiteID", null);
dsPlotNames.SelectParameters.Add("100mPlotName", lbl100mPlot.Text);
}
}
My next problem is this error:
Databinding methods such as Eval(), XPath(), and Bind() can only be used in the context of a databound control.
Exception Details: System.InvalidOperationException: Databinding methods such as Eval(), XPath(), and Bind() can only be used in the context of a databound control.
Source Error:
[No relevant source lines]
I'm not sure what's causing it.
I dont think you can do it this way. You can handle RowEditing event in code behind and manually adjust your SqlDataSource to display correct data. Also, move SqlDataSoruce out of your grid.
I'm looking to have a GridView displaying "Events" from a database, and then in the last column I want to do another database lookup (for each row) to see if that event is full or not.
If it's not full, display a radio button. If it is full display text "Full".
I think this is best done with OnRowDataBound event but could use a little help.
I can see how to change an asp label text but not display a radio button.
register.aspx:
<asp:GridView ID="GridView2" runat="server" DataSourceID="SqlDataSource2" AutoGenerateColumns=false CellPadding="5" HeaderStyle-BackColor="DarkGray" Width="450px" OnRowDataBound="GridView2_OnRowDataBound">
<Columns>
<asp:BoundField DataField="sessionDate" HeaderText="Date" DataFormatString="{0:D}" />
<asp:BoundField DataField="sessionTime" HeaderText="Time" />
<asp:BoundField DataField="site" HeaderText="Site" />
<asp:BoundField DataField="room" HeaderText="Room" DataFormatString="{0:D}" />
<asp:TemplateField HeaderText="">
<ItemTemplate>
<input type="radio" name="rdoSessionID" value='<%# Eval("ses_ID") %>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
<HeaderStyle BackColor="#99CCFF" />
</asp:GridView>
<br />
<asp:SqlDataSource ID="SqlDataSource2" runat="server" ConnectionString="<%$ ConnectionStrings:sqlConnection2 %>"
SelectCommand="SELECT * FROM dbo.sessions WHERE site LIKE #ses_site AND sessionDate = #ses_date ORDER BY sessionDate">
<SelectParameters>
<asp:SessionParameter name="ses_site" SessionField="ses_site" Type="String" />
<asp:SessionParameter name="ses_date" SessionField="ses_date" Type="String" />
</SelectParameters>
</asp:SqlDataSource>
There are a few ways you can do this.
You can do this on the OnRowDataBound , If the Item you're dealing with is a DataItem, grab the value you need from the current row, and do a quick DB Lookup
When you get your resultset back from the database, do another lookup on each event. This way when your data leaves your data layer / methods you already have everything you need.
Modify your SQL query to return this information with the list of events. You already know the Events, you could just have a sub query to query to see if it's full or not (or the # of people registered, and the Max # allowed so you can show that). This way you only have to do 1 hit against the database and it will save you a bunch of processing. (My favorite)
You would still need to overload the OnRowDataBound event for all 3 of those solutions. You'd hide the radio button if it was full, and ensure it was visible if the event was not full. The difference is where do you get your data.
Do you want to do:
1 Good hit (list of events)
X amounts of small hits for each event
or
1 Good hit for list of events + if each event is full or not.
If you want to entertain #3, post your SQL Query and we can go from there.
Quick example of the OnRowDataBound event.
protected void MyGridView_OnRowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
CheckBox cbox = (CheckBox)e.Row.FindControl("chkBox");
// Do some funky logic
cbox.Visible = Event.HasRoom; //Boolean Propery
// Or
cbox.Visible = Convert.ToBoolean(DataBinder.Eval(e.Row.DataItem, "HasRoom").ToString());
}
}
Update 1:
For your GridView, You can use
<ItemTemplate>
<asp:CheckBox runat="server" ID="Checkbox1" ToolTip=" Sign up For event " text="Event stuff" />
</ItemTemplate>
If you want to use a template, don't use a regular control, use a control.
For the query you could do the following. I'm not 100% sure on your table structure so I did it the way I normally would:
Table: Session (sess_id(PK), SessionDate, SessionTime, Site, Room)
Table: Registrants (RegistrantID (PK), sess_id (FK to Session), UserID (FK to users that are registered)
SELECT SessionDate, SessionTime, Site, Room, ses_ID,
(SELECT Count(ses_ID) FROM Registrants R WHERE R.Ses_ID= S.ses_Id) as [Registrants]
FROM dbo.Sessions s
Use the OnRowDataBound event, like this:
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
RadioButton radio = e.Row.FindControl("RadioButton1") as RadioButton;
if (radio != null)
{
radio.Visible = SomeCheckThatReturnsBoolean((int)GridView1.DataKeys[e.Row.RowIndex]["SomeID"]);
}
}
If possible though, you should return the data with the GridView results, and store the value in a data key, so you can do something like this:
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
RadioButton radio = e.Row.FindControl("RadioButton1") as RadioButton;
if (radio != null)
{
radio.Visible = (bool)GridView1.DataKeys[e.Row.RowIndex]["SomeBooleanValue"];
}
}
EDIT: Based on your comment to #Ryan, I think you should be able to include that flag in your query. I don't know your database at all, but you can try using a derived table or subquery to get the registrant session counts. Here's a rough example to work off of:
SELECT ID,
ISNULL(Registrants.RegistrantCount, 0) RegistrantCount
...
FROM Table1 t1
LEFT OUTER JOIN (
SELECT ForeignKeyID,
COUNT(RegistrantID) RegistrantCount
FROM Registrants
GROUP BY ForeignKeyID
) Registrants
ON Registrants.ForeignKeyID = t1.ID
So I have a gridview within a gridview (I have a one to many table) my first gridview is working well, but my second gridview has a sqldatasource that has a select parameter(the default value was just for testing)
<asp:SqlDataSource ID="dsCountryByTripID" runat="server"
ConnectionString="<%$ ConnectionStrings:bahDatabase %>"
SelectCommand="spSelectCitiesByTripID" SelectCommandType="StoredProcedure">
<SelectParameters>
<asp:Parameter Type="Int32" Name="tripID" DefaultValue="56" />
</SelectParameters>
</asp:SqlDataSource>
during my Gridview1 row databound I am trying to grab the columns that match the tripID. But dsCountryByTripID which is my datasource, is only going inputted with the last tripID.
protected void GridView1_RowDataBound1(object sender, GridViewRowEventArgs e)
{
GridView gv2 = (GridView)e.Row.FindControl("GridView2");
if (e.Row.RowType == DataControlRowType.DataRow)
{
dsCountryByTripID.SelectParameters.Clear();
DataRowView drv = (DataRowView)e.Row.DataItem;
string tripID = (drv["pkiTripId"]).ToString();
dsCountryByTripID.SelectParameters.Add("tripID", DbType.Int32, tripID);
//gv2.DataBind();
//e.Row.DataBind();
}
}
here you can read why it only executes the last "tripId": http://msdn.microsoft.com/en-us/library/tw738475(VS.80).aspx
The sql datasource only gets executed at the end of the page, so every time you go through a row the tripID is overriden.
Do you really need to use the datasource? Can't you use ado.net or something different for you dataaccess?
Hope this helps.
First, we need to clarify the structure of your page. It seems to me that dsCountryByTripID is declared outside of Gridview1, instead of inside Gridview1. That's probably why your dsCountryByTripID is only going inputted with the last tripID.
In order to do what you want, the structure should be like this:
<asp:gridview id="gv1" runat="server" DataSourceID="ds1">
...
<asp:gridview id="gv2nested" runat="server" DataSourceID="dsCountryByTripID">
</asp:gridview>
<asp:SqlDataSource ID="dsCountryByTripID" runat="server"
ConnectionString="<%$ ConnectionStrings:bahDatabase %>"
SelectCommand="spSelectCitiesByTripID" SelectCommandType="StoredProcedure">
<SelectParameters>
<asp:Parameter Type="Int32" Name="tripID" DefaultValue="56" />
</SelectParameters>
</asp:SqlDataSource>
...
</asp:gridview>
<asp:SqlDataSource ID="ds1" runat="server" >
</asp:SqlDataSource>
Next, to assign the correct value to the inner datasource selectparameter, you can do that in the outer gridview (gv1) RowCreated event handler.
protected void gv1_RowCreated(object sender, GridViewRowEventArgs e)
{
//Retrieve the inner gridview
//Retrieve the inner sqldatasource
//Retrieve and assign selectparameter value
}
It's similar to the C# code you posted, but you need to additionally use FindControl to retrieve the now nested sqldatasource (dsCountryByTripID) before assigning the value to the selectparameter. (Trying to teach a man fishing here, but let me know if you need more help or if the above is not your case :)