I have a GridView on an ASP. NET web form which is displaying some information from a table in a SQL database. I also have some buttons to delete, update and add new data. However, my delete button doesn't work. I keep getting the error "Object reference not set to an instance of an object."
I will post the function below with the data in the table. Can anyone assist me, please?
<asp:GridView ID="gvFarmer" runat="server"
BackColor="White" BorderColor="White" BorderStyle="Ridge" BorderWidth="2px" CellPadding="5" style="margin-right: 58px"
CellSpacing="1" GridLines="None" AutoGenerateColumns="false" Height="166px" Width="692px" ShowFooter="true" ShowHeaderWhenEmpty="true"
OnRowCommand="gvFarmer_RowCommand" OnRowEditing="gvFarmer_RowEditing" OnRowCancelingEdit="gvFarmer_RowCancelingEdit" OnRowUpdating="gvFarmer_RowUpdating" OnRowDeleting="gvFarmer_RowDeleting">
<FooterStyle BackColor="#C6C3C6" ForeColor="Black" />
<HeaderStyle BackColor="#4A3C8C" Font-Bold="True" ForeColor="#E7E7FF" />
<PagerStyle BackColor="#C6C3C6" ForeColor="Black" HorizontalAlign="Right" />
<RowStyle BackColor="#DEDFDE" ForeColor="Black" />
<SelectedRowStyle BackColor="#9471DE" Font-Bold="True" ForeColor="White" />
<SortedAscendingCellStyle BackColor="#F1F1F1" />
<SortedAscendingHeaderStyle BackColor="#594B9C" />
<SortedDescendingCellStyle BackColor="#CAC9C9" />
<SortedDescendingHeaderStyle BackColor="#33276A" />
<Columns> <%--Colums are created here --%>
<%-- COLUMN 1--%>
<%-- Creation of template field to hold column names and information for a table--%>
<asp:TemplateField HeaderText="Farmer ID"> <%-- here the filed is created--%>
<ItemTemplate>
<asp:Label Text='<%# Eval("Farmer_Id") %>' runat="server"></asp:Label> <%-- By default the filed will be a label for viewing--%>
<%-- The eval() function will binds the title of colums name in the database to the title in browser. So, if changes are made they are reflected --%>
</ItemTemplate>
<EditItemTemplate> <%-- when the field is clicked on to be eidted, it will be a textbox so the user can interact with--%>
<asp:TextBox ID="txtFarmerID" runat="server" Text='<%# Eval("Farmer_Id") %>'></asp:TextBox>
<%-- The eval() function will binds the title of colums name in the database to the title in browser. So, if changes are made they are reflected --%>
</EditItemTemplate>
<FooterTemplate><%-- This will be the default area from which new records are added to the table--%>
<asp:TextBox ID="txtFarmerIDFooter" runat="server"></asp:TextBox>
<%-- A textbox is used for getting the pieces of information to be added to the table--%>
</FooterTemplate>
</asp:TemplateField><%-- End of first column--%>
<%-- COLUMN 2--%>
<asp:TemplateField HeaderText="First Name">
<ItemTemplate>
<asp:Label Text='<%# Eval("FirstName") %>' runat="server"></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="txtFarmerFirstName" runat="server" Text='<%# Eval("FirstName") %>'></asp:TextBox>
</EditItemTemplate>
<FooterTemplate>
<asp:TextBox ID="txtFarmerFirstNameFooter" runat="server"></asp:TextBox>
</FooterTemplate>
</asp:TemplateField>
<%-- COLUMN 3--%>
<asp:TemplateField HeaderText="Last Name">
<ItemTemplate>
<asp:Label Text='<%# Eval("LastName") %>' runat="server"></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="txtFarmerLastName" runat="server" Text='<%# Eval("LastName") %>'></asp:TextBox>
</EditItemTemplate>
<FooterTemplate>
<asp:TextBox ID="txtFarmerLastNameFooter" runat="server"></asp:TextBox>
</FooterTemplate>
</asp:TemplateField>
Below is the C# Code for the Delete Function after you click the delete icon:
protected void gvFarmer_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
try
{
using (SqlConnection con = new SqlConnection(conStr))
{
con.Open();
string InsertQuery = "DELETE FROM Farmer WHERE Farmer_Id = #Farmer_Id";
//parametrized variables are used to prevent sql injection
SqlCommand insert = new SqlCommand(InsertQuery, con);
insert.Parameters.AddWithValue("#Farmer_Id", (gvFarmer.Rows[e.RowIndex].FindControl("txtFarmerID") as TextBox).Text.Trim());
//get the info from textbox, trim spaces and store it in appropirate fields in the database
insert.ExecuteNonQuery(); //function executes the insert query
PopulateGridView(); //function is called to show updated view.
lblSuccess.Text = "Record Deleted!";
lb1Error.Text = "";
}//using block ends here
}
catch (Exception ex)
{
lblSuccess.Text = "";
lb1Error.Text = ex.Message;
}//end of try catch
}
The most possible cause is this cast:
gvFarmer.Rows[e.RowIndex].FindControl("txtFarmerID") as TextBox
This cast will return null value if the row type is not DataRow or the control is not found on respective row and throwing NullReferenceException when using Text property. You should try using Cells property:
insert.Parameters.AddWithValue("#Farmer_Id", (gvFarmer.Rows[e.RowIndex].Cells[n].FindControl("txtFarmerID") as TextBox).Text.Trim());
n indicates the column index where txtFarmerID sets up (usually ID column set as index 0).
If it still doesn't work, add DataKeyNames attribute in the markup:
<asp:GridView ID="gvFarmer" runat="server" DataKeyNames="Farmer_Id" ...>
<%-- grid contents --%>
</asp:GridView>
Then try using DataKeys collection property:
insert.Parameters.AddWithValue("#Farmer_Id", gvFarmer.DataKeys[e.RowIndex].Value.ToString().Trim());
I think the latter approach is better because you don't need to find out the control which holds unique value to delete the row, since the key field name is already defined.
Similar issue:
GridView Edit and Delete "Object reference" error
Related
Greetings fellow developers. I am new to ASP.NET C# so pardon me if there are areas that I missed out/
Current in my project, I have this Gridview - where I used "TemplateField" for almost every data field. My issue is, I do not know how can I pass the value in to another page. I tried using SESSION but unfortunately, it is not working. I also tried using BOUNDFIELD, it works but it does not fulfil my project requirement as the default setting for BOUNDFIELD is textbox, I want it to be a DROPDOWN LIST control instead. Any kind advice would be much appreciated. Attached below is my codes.
WebForm1.aspx
<asp:GridView ID="Gridview1" runat="server" AutoGenerateColumns="False" OnPageIndexChanging="Gridview1_PageIndexChanging" OnRowCancelingEdit="Gridview1_RowCancelingEdit" OnRowCommand="Gridview1_RowCommand" OnRowDeleting="Gridview1_RowDeleting" OnRowEditing="Gridview1_RowEditing" OnRowUpdating="Gridview1_RowUpdating" ShowFooter="True" BorderStyle="None" BorderWidth="1px" CellPadding="3" CellSpacing="2" ShowHeaderWhenEmpty="True" Width="100%" CssClass="table table-responsive table-bordered" OnSelectedIndexChanged="Gridview1_SelectedIndexChanged" DataKeyNames="CID">
<Columns>
<asp:TemplateField HeaderText="Transaction ID">
<EditItemTemplate>
<asp:Label ID="lbleditid" runat="server" Text='<%# Bind("CID") %>'></asp:Label>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="lblid" runat="server" Text='<%# Bind("CID") %>'></asp:Label>
</ItemTemplate>
<HeaderStyle CssClass="hidden-xs" />
<ItemStyle CssClass="hidden-xs" />
</asp:TemplateField>
<asp:TemplateField HeaderText="CCID">
<EditItemTemplate>
<asp:Label ID="lblccid2" runat="server"></asp:Label>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="lblccid" runat="server" Text='<%# Bind("CCID") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Category" SortExpression="Category">
<EditItemTemplate>
<%--<asp:TextBox ID="txtBox_Cat" runat="server" Text='<%# Bind("Category") %>'></asp:TextBox>--%>
<asp:DropDownList ID="ddlCategory" runat="server" >
<asp:ListItem Value="--Select--">--Select--</asp:ListItem>
<asp:ListItem Value="Transportation">Transportation</asp:ListItem>
<asp:ListItem Value="Children">Children </asp:ListItem>
<asp:ListItem Value="Food">Food</asp:ListItem>
</asp:DropDownList>
</EditItemTemplate>
<FooterTemplate>
<asp:DropDownList ID="ddlCategory1" runat="server">
<asp:ListItem>--Select--</asp:ListItem>
<asp:ListItem>Transportation</asp:ListItem>
<asp:ListItem>Children </asp:ListItem>
<asp:ListItem>Food </asp:ListItem>
</asp:DropDownList>
</FooterTemplate>
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# Bind("Category") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Last Edited">
<EditItemTemplate>
<asp:TextBox ID="txtDateTime1" runat="server" Text='<%# Bind("Last_Edited") %>'></asp:TextBox>
</EditItemTemplate>
<FooterTemplate>
<asp:TextBox ID="txtDateTime" runat="server" ToolTip="DD/MM/YYYY"></asp:TextBox>
</FooterTemplate>
<ItemTemplate>
<asp:Label ID="lblDateTime" runat="server" Text='<%# Bind("Last_Edited") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Edit" ShowHeader="False">
<EditItemTemplate>
<asp:LinkButton ID="LinkButton1" runat="server" CausesValidation="True" CommandName="Update" Text="Update"></asp:LinkButton>
<asp:LinkButton ID="LinkButton2" runat="server" CausesValidation="False" CommandName="Cancel" Text="Cancel"></asp:LinkButton>
</EditItemTemplate>
<FooterTemplate>
<asp:LinkButton ID="LinkButton2" runat="server" CausesValidation="true" CommandName="AddNew" Text="Add New"></asp:LinkButton>
</FooterTemplate>
<ItemTemplate>
<asp:LinkButton ID="LinkButton1" runat="server" CausesValidation="False" CommandName="Edit" Text="Edit"></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
<asp:CommandField HeaderText="Delete" ShowDeleteButton="True" ShowHeader="True" />
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton ID="LinkButton3" runat="server" OnClick="PassData">Select</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
WebForm1.aspx.cs
protected void PassData(object sender, EventArgs e)
{
GridViewRow gr = ((sender as LinkButton).NamingContainer as GridViewRow);
Session["Category"] = gr.Cells[1].Text.Trim();
Response.Redirect("AfterUserMthlyExpenses.aspx");
}
WebForm2.aspx
<asp:Label ID="lblPassCategory" runat="server" ></asp:Label>
WebForm2.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
//Passing "Category" from previous page
lblPassCategory.Text = Session["Category"].ToString();
}
}
Well, really one should hold off on the passing of the value to the next page until such time you have a working simple answer to select/get the given row that you clicked on right?
Be it a repeater, grid view, list view (details view) etc.?
In asp.net they ALL FOLLOW the same process. You want to have that button click set/move/change to the correct given row that you clicked on. Until you have that “movement” or selection of the row occur, then you will fail at attempting to grab values from that row.
So, looking at this, you have a link button (it could be a asp.net button if want – don’t matter), you need that button to trigger/set/move/cause the row you are working on to change FIRST and BEFORE you attempt to grab data/values from that given row.
The WAY you do this is to add a special command. As noted, this works for list view/grivdview/repeater and MANY more data bound controls.
so what you learn here can apply to just about ANY data aware control (that repeats data).
So, add this to the one link button in the item template:
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton ID="LinkButton3" runat="server"
CommandName = "MyJump"
CommandArgument = '<%# Eval("Category") %>'
>Select</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
So, the INSTANT you add CommandName="Select", then this will cause TWO events of the grid to fire.
OnRowComand:
The row command event will fire. But the row HAS NOT YET changed!
However, since we use CommandArgument and pass "Catagory", then we of course can use the rowcomamnd event, and pick up the CommandArgument value.
So, you can have this code in row command event:
Protected Sub GridView1_RowCommand(sender As Object, e As GridViewCommandEventArgs) Handles GridView1.RowCommand
Debug.Print("row command = " & e.CommandName)
Debug.Print("row arg = " & e.CommandArgument)
If e.CommandName = "MySelect" Then
' do whatever
End If
End Sub
Note how we don't need (you can remove) the on-click event for that button - you use the rowcommand event stub, and pick up the custom command name you passed (MySelect).
You can ALSO trigger the selected row event to fire. This would allow you to use/keep/have your EXISTING code click stub for your button.
However you now MUST change the CommandName from "your custom" name to either;
Select (move the grid pointer)
Edit - trigger edit event
Delete - trigger delete event
However, in your button click (as you have now).
You could try this:
Dim btn As Button = sender
Dim gvRow As GridViewRow = btn.Parent.Parent
Debug.Print("btn row sel = " & gvRow.RowIndex)
Debug.Print("btn argument = " & btn.CommandArgument)
So you can try btn.Parent (that will be the grid cell, and parent again will return the ONE row as you have. From that, you can grab any value out of that row.
eg:
dim myLable as label
myLabel = gvRow.FindControl("Label1")
debug.print myLabel.Text (should return catagory).
Probably most easy to just add a CommandArgument, and pick it up from sender.
Now that you first and foremost verify that you have the correct value, then you can shove that value into session. in fact you can even shove in the whole gvRow into session, and thus pass all of the values of that row to the page you jump to.
I am fairly new to asp.net webforms and I have the following code to generate a grid with two columns,
I separated the columns using colours which I am able to do using e.Row.Cells[0].BackColor = Color.FromArgb(152, 251, 152);and for the second column e.Row.Cells[1].BackColor = Color.FromArgb(60, 179, 113) at the back end
what i am trying to achieve now is to colour the part of the GridView Header that is over the FirstColumn to the same colour as the first column and the second portion of the GridView Header that is over SecondCoumn to the same colour as the second column
Below is m y code
<asp:GridView ID="GridData" CssClass="Gridview" runat="server"
Width="100%" AutoGenerateColumns="False" OnRowDataBound="GridData_RowDataBound" ShowFooter="True">
<Columns>
<asp:TemplateField ItemStyle-Width="120px" HeaderText="ColumnFirst" >
<ItemTemplate>
<asp:Label ID="lblLoanGiven" runat="server"></asp:Label>
</ItemTemplate>
<FooterTemplate>
<asp:Label ID="lblTotalLoanGiven" runat="server"></asp:Label>
</FooterTemplate>
</asp:TemplateField>
<asp:TemplateField ItemStyle-Width="120px" HeaderText="ColumnSecond">
<ItemTemplate>
<asp:Label ID="lblLoanGivenBalance" runat="server"></asp:Label>
</ItemTemplate>
<FooterTemplate>
<asp:Label ID="lblTotalLoanGivenBalance" runat="server"></asp:Label>
</FooterTemplate>
</asp:TemplateField>
<PagerStyle BackColor="#3C8DBC" ForeColor="White" />
<HeaderStyle BackColor="#3C8DBC" ForeColor="White" />
<FooterStyle BackColor="#007C98" ForeColor="White" CssClass="footer-design" />
</asp:GridView>
GridData.HeaderRow.Cells[1].Style["background-color"] = "#3CB371";
Found the answer the above code colours my 2porions of the GridView headers
I have a problem with adding a new row with several controls like textBoxes into Header of GridView. When I add them into Header in GridView_RowCreated method with ...
if (e.Row.RowType == DataControlRowType.Header)
{
GridViewRow r = new GridViewRow(0, 0, DataControlRowType.Header, DataControlRowState.Normal);
TableCell tc = new TableCell();
.. they always are put into first row, not second. How can I change it? I want my created row put in second Header Row. I tried to do it by myself, Firstly, I modified ShowHeader into false and add both first and second rows programmatically, but it is wrong way, aspecially when grid has no data to show but it is necessary to show header. I found this discussion similar discussion, but intellisence doesn't know about override PrepareControlHierarchy. I tried to search it with Object browser, and found that this is method of GridView, but I couldn't plug it and test. Maybe somebody knows easier solution for this prob.
I need some assist.
UPDATED!!!
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
CellPadding="4" DataKeyNames="username" DataSourceID="SqlDataSource1"
ForeColor="#333333" GridLines="None" onrowcreated="GridView1_RowCreated">
<AlternatingRowStyle BackColor="White" />
<Columns>
<asp:TemplateField HeaderText="username" SortExpression="username">
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# Bind("username") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Name" SortExpression="Name">
<ItemTemplate>
<asp:Label ID="Label2" runat="server" Text='<%# Bind("Name") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Surname" SortExpression="Surname">
<ItemTemplate>
<asp:Label ID="Label3" runat="server" Text='<%# Bind("Surname") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
UPDATED!!!!
Yes, profs you are right, in my case it is the easiest way to put controls in HeaderTemplate. I forgot about it. But I have a little question, how can I add names of columns without adding additional Labels? Here is my code:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
CellPadding="4" DataKeyNames="username" DataSourceID="SqlDataSource1"
ForeColor="#333333" GridLines="None" onrowcreated="GridView1_RowCreated">
<AlternatingRowStyle BackColor="White" />
<Columns>
<asp:TemplateField **HeaderText="username"** SortExpression="username">
<HeaderTemplate>
**<asp:Label ID="Label4" runat="server" Text="username"></asp:Label>**<br />
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
</HeaderTemplate>
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# Bind("username") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Name" SortExpression="Name">
<HeaderTemplate>
<asp:Label ID="Label4" runat="server" Text="Name"></asp:Label><br />
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
</HeaderTemplate>
<ItemTemplate>
<asp:Label ID="Label2" runat="server" Text='<%# Bind("Name") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Surname" SortExpression="Surname">
<HeaderTemplate>
<asp:Label ID="Label4" runat="server" Text="Surname"></asp:Label><br />
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
</HeaderTemplate>
<ItemTemplate>
<asp:Label ID="Label3" runat="server" Text='<%# Bind("Surname") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
I marked bold strings. If I leave without Label (just with HeaderText="username") it isn't show me any name in header column. Only if I add Labels it shows my names. What is wrong with it?
Dynamically you would have to add a second header row after every has been databound
Example in VB but you should be able to convert it easily enough.
Private Sub GridView1_DataBound(sender As Object, e As EventArgs) Handles GridView1.DataBound
// Add checks for row count.
// create a new row
Dim gvr As New GridViewRow(0, 0, DataControlRowType.Header, DataControlRowState.Normal)
Dim gvc As TableCell
// Create a new empty cell
gvc = New TableCell()
//add a new TextBox to the cell
gvc.Controls.Add(New TextBox())
// Add the cell to the row
gvr.Cells.Add(gvc)
// repeat above as necessary
// Add row to Gridview at index 1 (0 is bound header)
// GridView1.Controls(0) is the Gridview table
GridView1.Controls(0).Controls.AddAt(1, gvr)
End Sub
The simplest solution is to not attempt to do it in the code behind. Instead utilize the HeaderTemplate for your TemplateFields.
Here is one as an example:
<asp:TemplateField HeaderText="username" SortExpression="username">
<HeaderTemplate>
username
<br />
<asp:TextBox ID="username" runat="server" />
</HeaderTemplate>
<ItemTemplate...
</asp:TemplateField>
So i got this gridview on ASP.NET, it is about a gmail client, i made a template field with a check box that is for select several message at the same time, but first when you select a message i want to change the row background color, I already have my CSS but i dont know how to trigger the action or how to know what row was selected in the code. Here is the template of my grid:
<asp:GridView ID="inboxGrid" runat="server"
AutoGenerateColumns="false" CssClass="inbox" ShowHeader="false" BorderStyle="None" GridLines="None">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:CheckBox ID="chkSelect" runat="server" />
</ItemTemplate>
<ItemStyle Width="24" CssClass="check"/>
</asp:TemplateField>
<asp:TemplateField>
<ItemStyle CssClass="from" />
<ItemTemplate>
<asp:Label ID="lblFrom" runat="server"
Text = '<%# Eval("From") %>' />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemStyle CssClass="subject" />
<ItemTemplate>
<asp:Label ID="lblSubject" runat="server" Text='<%# Eval("Subject") %>' />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemStyle CssClass="date" />
<ItemTemplate>
<asp:Label ID="lblFecha" runat="server" Text='<%# Eval("Fecha") %>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
<RowStyle CssClass="inbox"/>
</asp:GridView>
Here is a solution using JQuery
Provided you add a CssClass named chk to asp:checkbox
<asp:CheckBox ID="chkSelect" runat="server" CssClass="chk" />
Here is the script
$(document).ready(function () {
$(".chk :checkbox").live("click", function () {
$(this).closest("tr").css("background-color", this.checked ? "#0000FF" : "");
});
});
Try this:
<asp:CheckBox ID="chkSelect" runat="server" OnClick="changeCss(this.id);" />
You can use toggleClass('CssClassName') to toggle the class on checkbox clicks:
function changeCss(ctrlId){
$(ctrlId).parent().parent().toggleClass('check');
}
The hierarchy is tr > td > checkbox, we go reverse to change the css of tr/row.
I have a DetailsView that uses my Business Logic Layer in the code behind. I still use the DetailsView declaratively the same as if you drop a label control on the page but I don't declare a datasourceID in the attributes section of the XHTML.
After extensive searching on the web I noticed that most examples use a SqlDataSource declaratively and assign the id to the DetailsView datarouceID attribute.
I don't want to have the UI directly connected to the Data Logic Layer. I have a BLL that does all the busines end transactions and passes objects to the UI.
This is what my DetailsView looks like.
<asp:DetailsView ID="dvCapability"
runat="server"
Width="90%" AutoGenerateEditButton="true"
AutoGenerateRows="False"
EmptyDataText="Unable to retrieve the capability details."
BorderColor="LightGray"
BorderStyle="Solid"
BorderWidth="1px"
DataKeyNames="IAID" >
<AlternatingRowStyle CssClass="altrow" />
<EmptyDataRowStyle HorizontalAlign="Center" />
<Fields>
<asp:TemplateField HeaderText="Status:" HeaderStyle-Width="15%" ItemStyle-Width="85%">
<ItemTemplate>
<asp:Label ID="lblLabStatus" runat="server" Text='<%# Eval("LabStatus") %>' />
</ItemTemplate>
<EditItemTemplate>
<asp:DropDownList ID="ddLabStatus" runat="server" Width="200px" BackColor="White" Font-Size="10px" SelectedValue='<%# Bind("LabStatus") %>' />
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Type:" HeaderStyle-Width="15%" ItemStyle-Width="85%">
<ItemTemplate>
<asp:Label ID="lblLabType" runat="server" Text='<%# Eval("LabType") %>' />
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="tbLabType" runat="server" Text='<%# Bind("LabType") %>' Width="200px" BackColor="White" Enabled="false" Font-Size="10px" />
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="UIC:" HeaderStyle-Width="15%" ItemStyle-Width="85%">
<ItemTemplate>
<asp:Label ID="lblUIC" runat="server" Text='<%# Eval("UIC") %>' />
</ItemTemplate>
<EditItemTemplate>
<asp:DropDownList ID="ddUIC" runat="server" Width="200px" BackColor="White" Font-Size="10px" SelectedValue='<%# Bind("UIC") %>' />
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Org code:" HeaderStyle-Width="15%" ItemStyle-Width="85%">
<ItemTemplate>
<asp:Label ID="lblOrgCode" runat="server" Text='<%# Eval("OrgCode") %>' />
</ItemTemplate>
<EditItemTemplate>
<asp:DropDownList ID="ddOrgCode" runat="server" Width="200px" BackColor="White" Font-Size="10px" SelectedValue='<%# Bind("OrgCode") %>' />
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="VSYSCOM:" HeaderStyle-Width="15%" ItemStyle-Width="85%">
<ItemTemplate>
<asp:Label ID="lblVSYSCOM" runat="server" Text='<%# Eval("VSYSCOM") %>' />
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="tbVSYSCOM" runat="server" Text='<%# Bind("VSYSCOM") %>' Width="200px" BackColor="White" Font-Size="10px" />
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Name:" HeaderStyle-Width="15%" ItemStyle-Width="85%">
<ItemTemplate>
<asp:Label ID="lblLabName" runat="server" Text='<%# Eval("LabName") %>' />
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="tbLabName" runat="server" Text='<%# Bind("LabName") %>' Width="500px" BackColor="White" Font-Size="10px" />
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Description:" HeaderStyle-Width="15%" ItemStyle-Width="85%">
<ItemTemplate>
<asp:Label ID="lblLabDescription" runat="server" Text='<%# Eval("LabDescription") %>' />
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="tbLabDescription" runat="server" Text='<%# Bind("LabDescription") %>' TextMode="MultiLine" Width="500px" Height="75px" BackColor="White" Font-Size="11px" />
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Technical Capability:" HeaderStyle-Width="15%" ItemStyle-Width="85%">
<ItemTemplate>
<asp:Label ID="lblTechnicalCapability" runat="server" Text='<%# Eval("TechnicalCapability") %>' />
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="tbTechnicalCapability" runat="server" Text='<%# Bind("TechnicalCapability") %>' TextMode="MultiLine" Width="500px" Height="75px" BackColor="White" Font-Size="11px" />
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Facility:" HeaderStyle-Width="15%" ItemStyle-Width="85%">
<ItemTemplate>
<asp:Label ID="lblFacility" runat="server" Text='<%# Eval("Facility") %>' />
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="tbFacility" runat="server" Text='<%# Bind("Facility") %>' TextMode="MultiLine" Width="500px" Height="75px" BackColor="White" Font-Size="11px" />
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Notes:" HeaderStyle-Width="15%" ItemStyle-Width="85%">
<ItemTemplate>
<asp:Label ID="lblComments" runat="server" Text='<%# Eval("Comments") %>' />
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="tbComments" runat="server" Text='<%# Bind("Comments") %>' TextMode="MultiLine" Width="500px" Height="75px" BackColor="White" Font-Size="11px" />
</EditItemTemplate>
</asp:TemplateField>
<asp:CommandField ShowEditButton="true" />
</Fields>
<FooterStyle CssClass="footer" />
<HeaderStyle Width="15%" />
<PagerStyle CssClass="footer" />
<RowStyle CssClass="row" />
</asp:DetailsView>
I bind it to a DataTable that is returned from my BLL in the Page's codebhind like so.
Utilities.BindCompositeControl(dvCapability, Controller.GetCapability(getIaid()));
The BindCompositeControl() method is in a static class that I use to reduce redundatnt coding. The method is coded as follows:
public static void BindCompositeControl(CompositeDataBoundControl control, DataTable values)
{
control.DataSource = values;
control.DataBind();
}
However, when I try to use the Edit or Insert Buttons that are generated by the DetailsView control nothing happens. What am I missing in order to bind this control programatically and change it's operational state on the UI?
If you can post your code for your data source you are binding, that will help see if you've allowed inserting and updating which may be causing an issue.
However I suspect you may need to manually maintain the datasource as you change the mode of the DetailsView. When you click Edit / Insert it causes a postback and I believe it no longer has the datasource attached.
On the first load of the control, you'll attach the datasource but after that you need to recreate the control each time, probably by saving the control state to the ViewState, recreating the data source and pull the control state back out of the ViewState on each page load.
It sounds more complex than it is. One way to do this is by creating the datasource through the OnInit event for the page. If you need to maintain selected rows or pages, use the ViewState to maintain those details.
You should create the DataSource and bind it before the ViewState is up, so create the datasource and apply it in OnInit
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
datatype myData = /* .... */
//Create DataSource here
for (int i = 0; i < 10; i++) {
//Do something
myData.add(/* some data */);
}
dvCapability.DataSource = myData;
dvCapability.DataBind();
}
To add and delete items, you'll need to store the data in a way that is accessible to the rest of a page, such as Session[] and then remove / add items to that during the dvCapabilities_Inerting event, etc. After an add or delete you'll need to rebind the data with the updated data.
Take a gander at this http://weblogs.asp.net/infinitiesloop/archive/2006/08/03/Truly-Understanding-Viewstate.aspx. This sort of explains things under the 2. Persisting static data section.
For those of you who may run into this down the line. Here's what I came up with and it works. I add a value to the ViewState dictionary and set it in the Page_OnInit event handler. In the Page_PreRender event handler is where I bind the detailsview and set it's Mode. Please note that if you are using viewstate you must bind your data and change mode after the view state has loaded. the Page's Initialize method is called before the ViewState is loaded. Hope this helps those who need it. I found many posts that weren't successfully answered regarding this topic. Much thanks to Kirk for giving me a solid answer and a great lead on where I wanted to go.
public partial class About : System.Web.UI.Page
{
protected override void OnInit(EventArgs e)
{
if (!IsPostBack)
{
//Initially add the view state variable
ViewState.Add("DetailsViewMode", DetailsViewMode.ReadOnly);
}
base.OnInit(e);
}
protected override void OnPreRender(EventArgs e)
{
if (ViewState["DetailsViewMode"] != null)
{
//change the mode of the DetailsView
dvTest.ChangeMode((DetailsViewMode)ViewState["DetailsViewMode"]);
//Bind the details view to a source
//This is my own custom class but this is where you yould put
//DetailsView.Datasource = <source>
//DetailsView.DataBind()
Utilities.BindCompositeControl(dvTest, NadController.GetCapability(19));
}
base.OnPreRender(e);
}
protected void Page_Load(object sender, EventArgs e)
{
}
//Must handle ModeChanging event or you'll get a run time error when binding DetailsView programatically
protected void dvTest_ModeChanging(object sender, DetailsViewModeEventArgs e)
{
}
//Handles button clicks from the DetailsView control
protected void dvTest_OnItemCommand(object sender, DetailsViewCommandEventArgs e)
{
ViewState["DetailsViewMode"] = GetDetailsViewMode(e.CommandName);
}
protected DetailsViewMode GetDetailsViewMode(string mode)
{
switch (mode)
{
case Constants.Edit:
return DetailsViewMode.Edit;
case Constants.Insert:
return DetailsViewMode.Insert;
default:
return DetailsViewMode.ReadOnly;
}
}
}