asp.net sqldatasource detailview: how to set proper select statement - asp.net

My page load event looks like this....
SqlDataSource1.ConnectionString = Connection.ConnectionStr;
SqlDataSource1.SelectCommand = "select firstname,lastname from customer";
SqlDataSource1.InsertCommand = "CustRec_iu";
SqlDataSource1.InsertCommandType = SqlDataSourceCommandType.StoredProcedure;
SqlDataSource1.InsertParameters.Clear();
SqlDataSource1.InsertParameters.Add(new Parameter("firstname", DbType.String));
SqlDataSource1.InsertParameters.Add(new Parameter("LastName", DbType.String));
SqlDataSource1.InsertParameters.Add(new Parameter("Active",DbType.Int16,"1"));
The detailview control setting looks like this....
<asp:DetailsView ID="dvCustDetails1" runat="server" AutoGenerateRows="False"
DataSourceID="SqlDataSource1" Height="149px" Width="469px"
OnItemInserted=dvCustDetails1_ItemInserted
>
<Fields>
<asp:BoundField DataField="FirstName" HeaderText="First Name"
SortExpression="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="Last Name"
SortExpression="LastName" />
<asp:CommandField ButtonType="Button" ShowInsertButton="True" />
</Fields>
</asp:DetailsView>
Right after insert functionality is done, I would like to capture the custid from customer table which is identity column, some how extract it and select table with that record like
select * from customer where custid = #custid.
Then after the control renders after insert, I would like it to show the newly inserted record based on the above select statement.
Also, I would like detailsview to show update button so I could update the record.
How would i accomplish that??
I find very little documentation out there in google search or even print books.

You want to use the sqldatasource's OnSelected event with a return parameter from the SQL call.
Add this to the sqldatasource
OnSelected ="sqlds_Selected"
and implement it something like:
protected void sqlds_Selected(object sender, SqlDataSourceStatusEventArgs e)
{
//get the command object from the arg and
//then you can get to the parameter value
e.Command.Parameters["#CustomerID"].Value
//then set this to your detailsview key
}

Related

How to use Session to save value on current row of GridView, to be copied into TextBox? - VB.Net

I'm trying to use Session to record the data of the 1st column of current row to be used in another Web From which will be opened using a LinkButton that is in the GridView.
Basically, if I click the LinkButton on the 1st row, the 1st column data of the 1st row will be copied to the next Web Form. But before I do that, I want to do a smaller scale experiment to test it. So instead for now I want the Session to copy the data into a TextBox in the same form.
For reference, here is the design of the GridView, most rows removed since they're not relevant:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
BorderColor="Black" BorderStyle="Solid" BorderWidth="1px" Font-Names="Arial">
<AlternatingRowStyle BackColor="#B7DBFF" />
<Columns>
<asp:BoundField DataField="caseticket" HeaderText="Ticket #" >
<HeaderStyle BackColor="#000066" ForeColor="White" Wrap="False" width="10%"/>
<ItemStyle Wrap="False" />
</asp:BoundField>
<asp:TemplateField ShowHeader="False">
<HeaderStyle BackColor="#000066" ForeColor="White" Wrap="False" width="10%"/>
<ItemTemplate>
<asp:linkbutton ID="newLog" runat="server" onclick = "CaseLog_click" >Add Log </asp:linkbutton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<HeaderStyle BackColor="#000066" />
<RowStyle HorizontalAlign="Center" />
</asp:GridView>
For the TemplateField is a LinkButton with a onclick property. With it, I created the sub:
Sub CaseLog_click(ByVal sender As Object, ByVal e As EventArgs)
Session("ticket") = GridView1.SelectedRow.Cells(1).Text
'Response.Redirect("~/CaseLog.aspx") ==> will be using this to proceed to next Web Form
TextBox1.Text = Session("ticket") '==> For test use only.
End Sub
If I only kept the Response.Redirect("~/CaseLog.aspx") in the sub, the LinkButton can direct me to the next Web Form. But as it is now, during testing when I use the LinkButton I get an error on the session line of the sub.
Object reference not set to an instance of an object.
Is the code salvageable, or do I need to redo this?
Thanks.
It looks like the button event to select the row is not wired up.
I would use say this:
<asp:BoundField DataField="HotelName" HeaderText="HotelName" SortExpression="HotelName" />
<asp:ButtonField CommandName="Select" HeaderText="Select" ShowHeader="True" Text="Button" />
Note CAREFULL how we put the CommandName="Select" in above. If you don't do this, then the selected row does not come though correctly to the click event you have.
You could try the select command as per above on your link button, but I would just use the above. Now, hightlight the grid in the form desinger. On the properity sheet, go to events, and double click on the SelectedIndex Change event. So, your buttion is not changing the selected index correctly.
The code stub will look like this:
Protected Sub GridView1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles GridView1.SelectedIndexChanged
Dim lgridrow As GridViewRow = Me.GridView1.SelectedRow
Debug.Print("<" & lgridrow.Cells(0).Text & ">")
Debug.Print("<" & lgridrow.Cells(3).Text & ">")
Debug.Print("<" & Me.GridView1.SelectedRow.Cells(3).Text & ">")
End Sub
Note VERY careful how the event code stub is setup - the event args are different then yours.
So, you can try the CommandName="Select" in your existing code, but if not, then try the above button field as opposed to your custom asp.net button you have. As it stands, it don't look like your asp.net button is firing the row-changed event.
Edit and follow up:
Can I have extra buttons - run their own code?
Yes, you can. You can do this several ways (one is to pick up which button was clicked in the SelectedIndex change event.
Or, you can drop in extra buttons and use that event code stub.
So, in my example, lets add an extra button.
we now have this:
<Columns>
<asp:BoundField DataField="ID" HeaderText="ID" InsertVisible="False" ReadOnly="True" SortExpression="ID" />
<asp:BoundField DataField="LastName" HeaderText="LastName" SortExpression="LastName" />
<asp:BoundField DataField="FirstName" HeaderText="FirstName" SortExpression="FirstName" />
<asp:BoundField DataField="HotelName" HeaderText="HotelName" SortExpression="HotelName" />
<asp:ButtonField CommandName="Select" HeaderText="Select" ShowHeader="True" Text="Button" />
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton ID="LinkButton1" runat="server" OnClick="LinkButton1_Click"
CommandName="MySelect" CommandArgument ="<%# Container.DisplayIndex %>"
style="background-color:gray;color:white;text-decoration:none;padding-left:6px;padding-right:6px"
text="Mybutton"></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
We thus have this:
Now, we can attach/have button code for the extra button. But NOTE careful we did NOT use the built in SELECT for the command argument. The REASON is that if we have Command=select, then the selected index WILL fire, but AFTER our button code stub. That means we cannot use the selectedrow (too early).
So, what we do/did in above was have the CommandArguemnt PASS the selected row value - that value will pass ok, and thus we don't care that the selected index event does not fire (and by CHANGING our command argument to NOT "select", then in fact the selectedindexchange event DOES NOT fire.
As a result, we use the passed row in the command argument, and we have this for the button code:
Protected Sub LinkButton1_Click(sender As Object, e As EventArgs)
Dim ixrow As Integer = sender.CommandArgument
Debug.Print(Me.GridView1.Rows(ixrow).Cells(0).Text)
End Sub
And note while we are editing the markup, intel-sense will give a list of options when editing. Eg this:
So, that gives us a chance to wire up (add) a standard click event). No selected index code stub is required (since the button would fire before selected index anyway). So we are now manually wiring up this event. We are NOT thus using the selectedindex change event - we don't even need it.
So, now in our button stub, we are free to do anything we want - including jumping to another page
eg:
Protected Sub LinkButton1_Click(sender As Object, e As EventArgs)
Dim ixrow As Integer = sender.CommandArgument
Debug.Print(Me.GridView1.Rows(ixrow).Cells(0).Text)
Session("HotelName") = Me.GridView1.Rows(ixrow).Cells(3)
Response.Redirect("~/ShowHotelDetails.aspx")
End Sub
So, to add separate code buttons:
Don't use selected index change event - you MIGHT still want it to run but it will run/fire AFTER your button code (so can't use selectedrow - too early).
But, you do need Command="myjunk" because without a command, then the command argument does not work. By passing the row index in commandargument, then we are free to grab data from the gridview as per above code via row index.
So, you can well dump the selected index change event. You just have to pass the row index, and work from that. The code stub can thus walk the dog, setup values in session, or even pass/make the url with parameters.

Extract a BoundField to a Label

I have a DetailsView which works fine using a data access layer and a query string. However, I'd like to extract one of the fields and use it as the text in a label to go above the DetailsView as a title to that page.
Is this possible? And if so, how?
This is an abstract of the DetailsView:
<Fields>
<asp:BoundField DataField="bandname" HeaderText="Band" />
<asp:BoundField DataField="contactname" HeaderText="Contact" />
<asp:BoundField DataField="county" HeaderText="County" />
</Fields>
and the code behind:
if (Request.QueryString.Count != 0)
{
int id = int.Parse(Request.QueryString["bandid"]);
dtvBand.Visible = true;
List<Band> bandDetails = new List<Band> { BandDAL.AnonGetAllBandDetails(id) };
dtvBand.DataSource = bandDetails;
dtvBand.DataBind();
}
What I'd like to do is take the data in the first BoundField row and make it the text of a label. Pseudocode:
Label1.Text = (<asp:BoundField DataField="band")
I would not try to find the text on the DetailsView but in it's DataSource. You could use the DataBound event which is triggered after the DetailsView was databound, so it's ensured that the DataItem exists.
It depends on the Datasource of your DetailsView. Often it is a DataRowView. You have to cast it, then you can access it's column:
protected void DetailsView1_DataBound(Object sender, EventArgs e)
{
DetailsView dv = (DetailsView)sender;
string yourText = (string)((DataRowView)dv.DataItem)["ColumnName"];
Label1.Text = yourText;
}
If it's not a DataRowView use the debugger to see what dv.DataItem actually is.
I managed to achieve what I wanted using:
string titletext = dtvBand.Rows[0].Cells[1].Text.ToString();
dtvBand.Rows[0].Visible = false;
lblBand.Text = titletext;
It takes the first row of the DetailsView, puts it above the rest in a Label so it can be formatted as a header, then hides the first row of the DetailsView.
How about using a TemplateField as what Tim mentioned:
<Fields>
<asp:TemplateField>
<ItemTemplate>
<asp:Label ID="lblName" runat="server" Text='<%# Eval("Band") %>' />
</ItemTemplate>
</asp:TemplateField>
</Fields>

How to load Data from a second table in GridView

i have to tables: Users and PrivateMessages.
Users has UserID and Username.
PrivateMessages has the coloumns PMID and Text and SenderID.
(of course it has much more but to explain the problem, its enough)
Now I have a DataSource and a method like this:
public static List<UserPM> GetAllPMsAsSender(Guid userID)
{
using (RPGDataContext dc = new RPGDataContext())
{
return (from a in dc.UserPMs where a.Sender == userID && !a.IsDeletedSender orderby a.Timestamp select a).ToList();
}
}
and bind it to the ObjectDataSource with is bound to the Grid View.
The Grid view now looks like these:
<asp:ObjectDataSource ID="odsOutcome" runat="server"
SelectMethod="GetAllPMsAsSender" TypeName="DAL.PMDAL">
<SelectParameters>
<asp:CookieParameter CookieName="UserID" DbType="Guid" Name="userID" />
</SelectParameters>
</asp:ObjectDataSource>
<asp:GridView ID="gridOut" runat="server" AutoGenerateColumns="False"
DataSourceID="odsOutcome">
<Columns>
<asp:BoundField DataField="PMID" HeaderText="PMID" SortExpression="PMID" />
<asp:BoundField DataField="Text" HeaderText="Text" SortExpression="Text"/>
<asp:BoundField DataField="UserID" HeaderText="UserID" SortExpression="UserID" />
</Columns>
</asp:GridView>
So how I can get the Username in this field instead the UserID?
Try using join and select the user name too for your object data source and use the user name to display it instead of user id.
Refer this link How to do a join in linq to sql with method syntax?

How to get the non visible gridview cell value in ASP.net?

I have a grid like below.
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" s
onrowcommand="GridView1_RowCommand">
<Columns>
<asp:ButtonField DataTextField="Name" HeaderText="Name" />
<asp:BoundField DataField="ArrDate" DataFormatString="{0:MM/dd/yyyy}"
HeaderText="Arr Date" />
<asp:BoundField HeaderText="Dep Date" DataField="DepDate"
DataFormatString="{0:MM/dd/yyyy}" />
<asp:BoundField HeaderText="Mail" DataField="Mail" />
<asp:BoundField HeaderText="Status" DataField="Status" />
<asp:BoundField DataField="ResId" HeaderText="ResId" Visible="False" />
</Columns>
</asp:GridView>
In Code Behind:-
try
{
string text = GridView1.Rows[2].Cells[5].Text;
ScriptManager.RegisterStartupScript(this, GetType(), "Message", "alert('ResId = " + text + ".');", true);
}
catch { }
Now the message shows - RegId =.
I can't get the value. So I change the RedId BoundField as vissible. Now I got the Value.
that is RegId =6.
I have two issue now -
1) How to get the RegId value in Non Visible Column.
2) How I find the Row value which i click... bzs the only i can change the ROWVALUE in code..
string text = GridView1.Rows[ROWVALUE].Cells[5].Text;
That is certainly not the right way to do it. You might want to look at using DataKeys to achieve this. With current approach, when you add a new column to your grid your code will fail.
Add your RegId column inside DataKeys property on your gridview
Reference your gridview datakey for the current row in codebehind like this
int regId= Convert.ToInt32(YourGridview.DataKeys[rowIndex]["RegId"].ToString());

Data binding boundfields in web form

I have the following DetailsView, with several BoundFields, and SQlDataSource that populates the fields:
<asp:DetailsView ID="DetailsView1" runat="server" AutoGenerateRows="False" DataKeyNames="TICKET_ID"
DataSourceID="SqlDataSource1" HeaderText="Completed IT ticket information"
CellPadding="4" ForeColor="#333333" GridLines="None" HorizontalAlign="Center">
<Fields>
<asp:BoundField DataField="TICKET_ID" SortExpression="TICKET_ID" Visible="False" />
<asp:BoundField DataField="SUBMITTED_BY" SortExpression="SUBMITTED_BY" Visible="False" />
<asp:BoundField DataField="TICKET_TITLE" HeaderText="Ticket Description" SortExpression="TICKET_TITLE" />
<asp:BoundField DataField="SUBMITTED_BY" HeaderText="Submitted By" SortExpression="SUBMITTED_BY" />
<asp:BoundField DataField="SOLUTION_NOTES" HeaderText="Solution Notes" SortExpression="SOLUTION_NOTES" />
<asp:BoundField DataField="EMAIL_HISTORY" HeaderText="Email History" SortExpression="EMAIL_HISTORY" />
<asp:BoundField DataField="COMPLETED_BY" HeaderText="Completed By" SortExpression="COMPLETED_BY" />
<asp:BoundField DataField="COMPLETE_DATE" HeaderText="Completed Date" ReadOnly="True" SortExpression="COMPLETE_DATE" />
</Fields>
</asp:DetailsView>
</div>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:TTPRODConnectionString %>"
SelectCommand="SELECT USR_ITFAC.TS_ID AS TICKET_ID, USR_ITFAC.TS_EC1_SUBMITTER AS SUBMITTED_BY, USR_ITFAC.TS_TITLE AS TICKET_TITLE, USR_ITFAC.TS_SOLUTION_NOTES AS SOLUTION_NOTES, USR_ITFAC.TS_EMAIL_HISTORY AS EMAIL_HISTORY, TS_USERS.TS_NAME AS COMPLETED_BY, DATEADD(HOUR,-8,USR_ITFAC.TS_CLOSEDATE) AS COMPLETE_DATE FROM USR_ITFAC INNER JOIN TS_USERS ON USR_ITFAC.TS_COMPLETED_BY = TS_USERS.TS_ID WHERE (USR_ITFAC.TS_ISSUEID = '00033')">
<SelectParameters>
<asp:QueryStringParameter Name="ts_id" QueryStringField="id" />
</SelectParameters>
</asp:SqlDataSource>
I hard-coded a value at the end of the query '00033', which is the ID of a record I know is in the database. I tested the query and it returns a value as expected, what I'm trying to do is fetch the values of the BoundField in the code-behind after a user has pressed a button.
Protected Sub btnSubmit_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Try
''Use a Dictionary to store answers to questions that were marked poor or fair
Dim answers As New Dictionary(Of String, String)
''For Each test
For Each dv_row As DetailsViewRow In DetailsView1.Rows
''Print rows data to console
Next
Catch ex As Exception
lblWarn.Text = "<br /><b>Please answer all the questions on this survey</b><br />"
'Response.Write(ex)
End Try
End Sub
Above I'm doing a test to fetch the values and print them onscreen, the problem is that the row count is 0, I'm not sure why that is. I expected the row count to be 8, when debugging I notice that the field count is 8, but I'm not sure how to get the values from the fields. I thought the way to get row data was something like:
Dim rowText As String = DetailsView1.Rows(0).Cells(1).Text
But when I try that I get a Null exception. Any insight is appreciated.
I misread the code. FindControl() is effective when using templates.
Try instead to use the FindControl(controlID) method on your details view to find your data-bound control. The method returns an object of type Control, so you'll probably have to type cast the result to get any real use out of it.
Was able to get it up and running. Turns out the BoundFields were not getting populated because the parameter in the QueryStringField, namely "id", was not being specified in the request URL. To resolve this I first tried to rewrite the URL path on Page_Load, that didn't work, so I just created a separate page with a hyperlink to the page I'm working on with a variable appended to the end of the URL which provides the QueryString for the SQLDataSource to reference. More on the QueryString property here.

Resources