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 :)
Related
I have a page I need to modify. The page was written by another developer. The page already had a combobox and function that allowed the user to select an author's name, click a button, then add that author's name to their wish list. I need to add another combobox that displays the library's genres, display the authors associated with that genre, then allow the user to click a button and add all those authors to their reading wish list. Here is the code with both the author and the genre comboboxes and the script that I'm attempting to use to insert all the authors when a genre is selected:
<asp:DropDownList ID="ddlGenres" runat="server" DataSourceID="SqlDataSourceLibros"
DataTextField="Genre_Name" DataValueField="GenreID"
onselectedindexchanged="genreList_SelectedIndexChanged" AutoPostBack="True" AppendDataBoundItems="true">
<asp:ListItem Value="0">Groups</asp:ListItem>
</asp:DropDownList>
<asp:SqlDataSource ID="SqlDataSource1Libros" runat="server"
ConnectionString="<%$ ConnectionStrings:Libros %>"
SelectCommand="SELECT [GenreID],[Genre_Name] FROM [Library_Genres] ORDER BY [Genre_Name]">
</asp:SqlDataSource>
<asp:DropDownList ID="DropDownList1" runat="server" AppendDataBoundItems="True"
DataSourceID="SqlDataSourceLibros2" DataTextField="Author_Name" EnableViewState="false"
DataValueField="Genre_Name">
</asp:DropDownList>
<asp:ImageButton ImageUrl="~/buttons/addGenre.png" Height="18px"
OnMouseOver="this.src='../buttons/addGenreHover.png'"
OnMouseOut="this.src='../buttons/addGenre.png'"
ToolTip="Add Library Genre" runat="server" ID="btnAddGenre"
OnClick="btnAddGenre_Click" />
<asp:SqlDataSource ID="SqlDataSource2" runat="server"
ConnectionString="<%$ ConnectionStrings:Libros %>"
SelectCommand="SELECT [Author_Name] FROM [Library_authors] WHERE ([Genre_Name] = #Genre_Name)">
<SelectParameters>
<asp:ControlParameter ControlID="ddlGroups" Name="Author_Name"
PropertyName="SelectedValue" Type="String" />
</SelectParameters>
</asp:SqlDataSource>
And now the script that is called by clicking the button:
protected void btnAddAuthors(object sender, EventArgs e)
{
odsAuthors.Insert();
AuthorList.ClearSelection();
Response.Redirect(Request.Url.AbsoluteUri);
}
protected void btnAddGenre(object sender, EventArgs e)
{
SqlDataSourceLibros2.Insert();
ddlGenres.ClearSelection();
Response.Redirect(Request.Url.AbsoluteUri);
}
My problem is that when I click the Add Genres button, the event that adds the individual author fire and is inserted - not all of the authors that appear in the combo box - depending on what genre is selected.
How can I get the list of authors to be inserted into the database like the individual author is inserted into the database when the AddAuthors button is clicked?
Check this answer, you cannot use ordinary select box - as it really has only one value, you should use controls for multiple selection, after this - you cannot populate them with authors, them them all as selected/checked and then you will get all values in your C# code, then you will be able to insert them all with for
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" />
When the user selects a row to edit I have a dropdownlist as one of the controls. In order for me to populate that ddl I need one of the datakeyname values (there are three). I was guessing that I could retrieve this value when the OnEditing event fired and pass it to the select statement for the ddl. Just not sure how to do this. I am using a stored procedure to query the Database.
This is my sqldatasource for the ddl -
<asp:SqlDataSource ID="SqlDataSourceDebtor" runat="server"
ConnectionString="<%$ ConnectionStrings:AuditDevConnectionString2 %>"
SelectCommand="sp_fc_vm_getDebtorList" SelectCommandType="StoredProcedure">
<SelectParameters>
<asp:ControlParameter ControlID="GridView1" DefaultValue="0" Name="ClientKey"
PropertyName="SelectedValue" Type="Int32" />
</SelectParameters>
</asp:SqlDataSource>
The "ClientKey" is the datakeyname value I need.
There are multiple approach to do this, please check http://weblogs.asp.net/aghausman/archive/2009/01/08/get-primary-key-on-row-command-gridview.aspx
Let me know if you want anything specific other than this.
I did a post on this a while back here: http://peterkellner.net/2006/10/14/showallingridviewfromddl/
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
For SqlDataSource I can configure the external source for the incoming paramater.
For example it might be a QueryString, Session, Profile and so on.
However I do not have an option to use User as a source.
I know that I could provide value for the parameter in Inserting,Selecting,Updating,Deleting events. But I do not think that this is an ellegant solution because I have some parameteres already definied in aspx file. I do not want to have parameters defined in two separate places. It makes mess.
So can I somehow define this parameter in .aspx file?
<SelectParameters>
<asp:QueryStringParameter DefaultValue="-1" Name="ID"
QueryStringField="ID" />
//User.Identity.Name goes here as a value for another parameter
</SelectParameters>
Declare it in your .aspx and fill it in your codebehind:
aspx
<asp:Parameter Name="username" Type="String" DefaultValue="Anonymous" />
codebehind
protected void Page_Init(object sender, EventArgs e) {
DataSource.SelectParameters["username"].DefaultValue = User.Identity.Name;
}
You can also accomplish this by creating a hidden textbox on the page, apply the User.Identity.Name to the value and then use the formcontrol parameter in the SQL data source. The advantage here is that you can reuse the code in the select, insert, delete, and update parameters without extra code.
So in aspx we have (noneDisplay is a css class to hide it):
<asp:TextBox runat="server" ID="txtWebAuthUser" CssClass="noneDisplay"></asp:TextBox>
and in the Update parameter of the sql datasource update section:
<asp:ControlParameter Name="CUrrentUser" ControlID="txtWebAuthUser" Type="String" PropertyName="Text" />
which gets interpreted in the update something like this:
UpdateCommand="UPDATE [Checks] SET [ScholarshipName] = #ScholarshipName, [Amount] = #Amount,LastModifiedBy=#CUrrentUser,
[LastModified] = getdate() WHERE [CheckId] = #CheckId"
and then in the .cs file form load we have:
this.txtWebAuthUser.Text = User.Identity.Name;
This technique has worked well in many places in all of our applications.
in asp page put a blank datasource with a connectionstring
e.g.
<asp:SqlDataSource ID="SqlDataSourceDeviceID" runat="server" ConnectionString="<%$ ConnectionStrings:myConnectionString %>">
<asp:DropDownList ID="DropDownListDeviceID" runat="server" DataSourceID="SqlDataSourceDeviceID" DataTextField="DevLoc" DataValueField="DeviceId"></asp:DropDownList>
in code behind on pageload
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack) {
String myQuery =String.Format("SELECT DeviceID,DevLoc FROM ... where UserName='{0}')",User.Identity.Name);
SqlDataSourceDeviceID.SelectCommand = myQuery;
SqlDataSourceDeviceID.DataBind();
DropDownListDeviceID.DataBind();
}