Create gridview datatable/source code behind error - c#

On my page, there are two gridviews where data are added to them dynamically using code behind. There are no problems with the code as far as I can see, the first gridview runs fine, but as soon as I want to add data to the second it gives me the error of:
Column 'LabourType' does not belong to table Table1
This is the error it gives when I initialize the labour grid first (Everything goes through fine). However, if I initialize the PartsGrid first it gives me the same error, just with the first column name of the parts grid.
This is what I have done in the Page_Load:
DataTable dtParts;
DataTable dtLabour;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
PopulateCustomers();
dtLabour = new DataTable();
MakeDataTableLabour();
EmptyDataStringLabour();
this.gvLabour.EditIndex = -1;
dtParts = new DataTable();
MakeDataTableParts();
EmptyDataStringParts();
this.gvParts.EditIndex = -1;
}
else
{
dtLabour = (DataTable)ViewState["DataTable"];
dtParts = (DataTable)ViewState["DataTable"];
}
ViewState["DataTable"] = dtLabour;
ViewState["DataTable"] = dtParts;
}
Can anybody please tell me if I am doing anything wrong? Or how can I solve this to allow both grids for data to be added dynamically? Thanks in advance
EDIT - More Data
For the Parts Grid this is how I create and add data to the datatable:
private void MakeDataTableParts()
{
dtParts.Columns.Add("Units");
dtParts.Columns.Add("PartNo");
dtParts.Columns.Add("Description");
dtParts.Columns.Add("CostPrice");
}
private void AddToDataTableParts()
{
DataRow drParts = dtParts.NewRow();
drParts["Units"] = txtUnits.Text.Trim();
drParts["PartNo"] = txtPartNo.Text.Trim();
drParts["Description"] = txtDescription.Text.Trim();
drParts["CostPrice"] = txtCostPrice.Text.Trim();
dtParts.Rows.Add(drParts);
}
private void BindGridParts()
{
gvParts.DataSource = dtParts;
gvParts.DataBind();
}
And for the labour:
private void MakeDataTableLabour()
{
dtLabour.Columns.Add("Units");
dtLabour.Columns.Add("LabourType");
dtLabour.Columns.Add("LabourCost");
}
private void AddToDataTableLabour()
{
DataRow drLabour = dtLabour.NewRow();
drLabour["Units"] = txtLabourUnits.Text;
drLabour["LabourType"] = lstLabourType.SelectedValue.ToString();
drLabour["LabourCost"] = txtLabourCost.Text;
dtLabour.Rows.Add(drLabour);
}
private void BindGridLabour()
{
gvLabour.DataSource = dtLabour;
gvLabour.DataBind();
}
This is how my gridviews are created in .aspx
Parts:
<asp:GridView ID="gvParts" runat="server" AutoGenerateColumns="true" CellPadding="8" CellSpacing="8" AllowPaging="false"
Width="100%" OnPageIndexChanging="gvParts_PageIndexChanging" OnRowCommand="gvParts_RowCommand"
OnRowCancelingEdit="gvParts_RowCancelingEdit" OnRowEditing="gvParts_RowEditing"
OnRowUpdating="gvParts_RowUpdating" OnRowDeleting="gvParts_RowDeleting" >
<emptydatatemplate>
There are currently no parts listed.
</emptydatatemplate>
<Columns>
<asp:TemplateField HeaderText="">
<ItemTemplate>
<asp:LinkButton ID="lnkEditParts" runat="server"CommandName="EditParts" CommandArgument='<%# Container.DataItemIndex %>'>Edit</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="">
<ItemTemplate>
<asp:LinkButton ID="lnkRemoveParts" runat="server" CommandName="DeleteParts" CommandArgument='<%# Container.DataItemIndex %>'>Remove</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<HeaderStyle CssClass="Grid" />
<RowStyle CssClass="rowStyle" />
<AlternatingRowStyle CssClass="alt" />
<PagerStyle CssClass="pgr" />
</asp:GridView>
Labour:
<asp:GridView ID="gvLabour" runat="server" AutoGenerateColumns="true" CellPadding="8" CellSpacing="8" AllowPaging="false"
Width="100%" OnPageIndexChanging="gvLabour_PageIndexChanging" OnRowCommand="gvLabour_RowCommand"
OnRowCancelingEdit="gvLabour_RowCancelingEdit" OnRowEditing="gvLabour_RowEditing"
OnRowUpdating="gvLabour_RowUpdating" OnRowDeleting="gvLabour_RowDeleting" >
<emptydatatemplate>
There are currently no labour listed.
</emptydatatemplate>
<Columns>
<asp:TemplateField HeaderText="">
<ItemTemplate>
<asp:LinkButton ID="lnkEditLabour" runat="server"CommandName="EditLabour" CommandArgument='<%# Container.DataItemIndex %>'>Edit</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="">
<ItemTemplate>
<asp:LinkButton ID="lnkRemoveLabour" runat="server" CommandName="DeleteLabour" CommandArgument='<%# Container.DataItemIndex %>'>Remove</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<HeaderStyle CssClass="Grid" />
<RowStyle CssClass="rowStyle" />
<AlternatingRowStyle CssClass="alt" />
<PagerStyle CssClass="pgr" />
</asp:GridView>
I'm binding the grids on the button click events (modal popop) as follows:
protected void btnSubmitPart_Click(object sender, EventArgs e)
{
AddToDataTableParts();
BindGridParts();
ClearPartsToAddNewItem();
}
protected void btnSubmitLabour_Click(object sender, EventArgs e)
{
AddToDataTableLabour();
BindGridLabour();
ClearLabourToAddNewItem();
}

Error is self explanatory. You have set column LabourType either as DataField or used this column in databing expression in one of your GridView but this column is not present in DataSource.

Related

How to create hyper links on rows of gridview that is derived from database in asp.net?

I m making a website in which i have used grid view table and retrieved data from database table category as shown down :
Database table category
I want to create link on rows i.e family tours ,religious tour ,Adventure Tours,Special Event Tours,National Park and whenever new row is created in table hyperlink should be created automatically on it .... How should I do it Please do help .... thank you
I want create link on data that is inside the red mark
Try this, I develop for you:
.aspx
<asp:GridView ID="GridView1" OnRowCommand="GridView1_RowCommand" AutoGenerateColumns="false" runat="server">
<Columns>
<asp:TemplateField>
<HeaderTemplate>
Page
</HeaderTemplate>
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# Bind("page") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<HeaderTemplate>
Navigation
</HeaderTemplate>
<ItemTemplate>
<asp:HiddenField ID="hdn_navigation" Value='<%# Bind("navigation") %>' runat="server" />
<asp:LinkButton ID="LinkButton1" CommandName="navigation" runat="server">Click Me</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Code Behind .cs:
private void load_gridView()
{
DataTable dt = new DataTable();
dt.Columns.Add("page");
dt.Columns.Add("navigation");
DataRow dr = dt.NewRow();
dr["page"] = "family tours";
dr["navigation"] = "family_tours.aspx";
dt.Rows.Add(dr);
DataRow dr2 = dt.NewRow();
dr2["page"] = "religious tour";
dr2["navigation"] = "religious_tour.aspx";
dt.Rows.Add(dr2);
GridView1.DataSource = dt;
GridView1.DataBind();
}
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
GridViewRow row = (GridViewRow)((Control)e.CommandSource).NamingContainer;
HiddenField hdn_navigation = (HiddenField)row.FindControl("hdn_navigation");
if (e.CommandName.ToString() == "navigation")
{
Response.Redirect(hdn_navigation.Value);
}
}
calling function from Page_Load():
protected void Page_Load(object sender, EventArgs e)
{
load_gridView();
}
Thank you for your help really appreciate your help #Rana Ali
I have got a more simplified method that can be done by just writing this code I hope this will help others as well :)
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataSourceID="SqlDataSource1" GridLines="None" Height="300px"
Width="100px">
<Columns>
<asp:BoundField DataField="Cat_name" HeaderText="Category"
SortExpression="Cat_name" >
<HeaderStyle Font-Bold="True" Font-Italic="True"
Font-Names="Lucida Calligraphy" Font-Size="X-Large" ForeColor="#3399FF" />
<ItemStyle Font-Bold="True" Font-Italic="True" Font-Size="Small" />
</asp:BoundField>
<asp:HyperLinkField DataTextFormatString="View" DataTextField="Cat_url" DataNavigateUrlFields="Cat_url" HeaderText="" />
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$ ConnectionStrings:ToursandTravelsConnectionString %>"
SelectCommand="SELECT [Cat_name], [Cat_url] FROM [category]">
This is and output of the code above :

Container.DisplayIndex not working with paging in ASP.NET

I have a gridview that is bound with data from code behind. Paging is applied in gridview. Everything works fine. For showing Row-Index i use Container.DisplayIndex.
When i go to next page through paging, every time gridview bind perfectly but DisplayIndex start with 1 to pagesize. I don't know what is wrong with the code.
Here is Asp.NET Code:
<asp:GridView runat="server" ID="dlAddress" AutoGenerateColumns="false" AllowPaging="True" OnPageIndexChanging="dlAddress_PageIndexChanging" >
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:Label ID="lblRowNumber" Text='<%# Container.DisplayIndex + 1 %>' runat="server" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
<PagerStyle HorizontalAlign="Center"/>
</asp:GridView>
C# Code:
public void bindGridView()
{
DBACon.Open();
SqlCommand Cmd = new SqlCommand("getAddresses", DBACon);
Cmd.CommandType = CommandType.StoredProcedure;
SqlDataAdapter AHadp = new SqlDataAdapter(Cmd);
AHadp.Fill(DS);
dlAddress.DataSource = DS;
dlAddress.DataBind();
}
protected void dlAddress_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
dlAddress.PageIndex = e.NewPageIndex;
bindGridView();
}
Here,
ASPX:
<asp:GridView ID="GridView1" runat="server" AllowPaging="True" PageSize="5" AutoGenerateColumns="False" DataKeyNames="AddressID" DataSourceID="SqlDataSource1">
<Columns>
<asp:TemplateField HeaderText="RowNumber">
<ItemTemplate>
<%# (GridView1.PageSize * GridView1.PageIndex) + Container.DisplayIndex + 1%>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>

How to populate multiple textboxes from a row in gridview that uses a link button

I'm trying to populate multiple text boxes with data from a gridview when I click the link button (which is in fact the name of one of the fields in each row) but it isn't going through. I'm new to this - literally my first time. Any help would be most appreciated.
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "Select")
{
int index = Convert.ToInt32(e.CommandArgument);
GridViewRow selectedRow = GridView1.Rows[index];
AccountNumber.Text = selectedRow.Cells[1].Text;
Name.Text = selectedRow.Cells[1].Text;
Address1.Text = selectedRow.Cells[1].Text;
Address2.Text = selectedRow.Cells[2].Text;
Address3.Text = selectedRow.Cells[3].Text;
PhoneNumber.Text = selectedRow.Cells[4].Text;
FaxNumber.Text= selectedRow.Cells[5].Text;
CurrencyID.Text = selectedRow.Cells[6].Text;
}
}
<asp:GridView ID="GridView1" runat="server"
AutoGenerateColumns="False"
DataKeyNames="Agent_Account_No"
DataSourceID="SqlDataSource1"
AlternatingRowStyle-BackColor ="Lavender"
HeaderStyle-BackColor="#9966FF"
AllowSorting="True" HeaderStyle-BorderColor="Black"
HorizontalAlign="Center"
RowStyle-BorderColor="Black"
EmptyDataText="There are no data records to display."
onrowcommand ="GridView1_RowCommand">
<AlternatingRowStyle BackColor="#CCFFCC" />
<Columns>
<asp:BoundField datafield="Agent_Account_No" HeaderText="Account No"
ItemStyle-HorizontalAlign="Center"
ItemStyle-VerticalAlign="Middle"
ItemStyle-Width="50"
SortExpression="Agent_Account_No"
ReadOnly="true">
<ItemStyle HorizontalAlign="Center" VerticalAlign="Middle"
Width="50px" />
</asp:BoundField>
<asp:TemplateField HeaderText="Name" SortExpression="Agent_Name">
<ItemTemplate>
<asp:LinkButton ID="AgentName" runat="server"
Text='<%# Eval("Agent_Name") %>'
CommandName="Select"
CommandArgument='<%#Bind("Agent_Name") %>'>
</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
I got it to work this way - using help from this site:
protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)
{
GridViewRow row = GridView1.SelectedRow;
AccountNumber.Text = GridView1.DataKeys[row.RowIndex]["Agent_Account_No"].ToString();
......
}
I don't know if this declaration is right, but it works. However now that it works I see a problem that I didn't see before - see my profile and thanks a lot!
I would highly recommend using TemplateFields for all of your columns, like this:
Markup:
<Columns>
<asp:TemplateField HeaderText="Account No" SortExpression="Agent_Account_No">
<ItemTemplate>
<asp:Label ID="LabelAccountNumber" runat="server"
Text='<%# Eval("Agent_Account_No") %>'>
</asp:Label>
</ItemTemplate>
</asp:TemplateField>
...
<asp:TemplateField HeaderText="Name" SortExpression="Agent_Name">
<ItemTemplate>
<asp:LinkButton ID="AgentName" runat="server"
Text='<%# Eval("Agent_Name") %>'
CommandName="Select"
CommandArgument='<%#Bind("Agent_Name") %>'>
</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
Now in the RowCommand method, you can use the FindControl() method of the grid view row to get to the text you are interested in, like this:
Code-behind:
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "Select")
{
int index = Convert.ToInt32(e.CommandArgument);
GridViewRow selectedRow = GridView1.Rows[index];
// Find the account number label to get the text value for the text box
Label theAccountNumberLabel = selectedRow.FindControl("LabelAccountNumber") as Label;
// Make sure we found the label before we try to use it
if(theAccountNumberLabel != null)
{
AccountNumber.Text = theAccountNumberLabel.Text;
}
// Follow the same pattern for the other labels to get other text values
}
}

How should I set gridview pager value when row is hidden

I have an issue where the pager number doesn't get updated automatically when I hide rows in the gridview. Do I need to set the pager value manually? Can someone suggest me on this?
ASPX page
<asp:GridView ID="SearchResults" runat="Server" AutoGenerateColumns="false"
EnableViewState="false" AllowPaging="true" PageSize="50"
OnDataBound ="SearchResults_DataBound"
OnRowDataBound="SearchResults_RowDataBound">
<RowStyle CssClass="EvenRow" />
<AlternatingRowStyle CssClass="OddRow" />
<Columns>
<asp:TemplateField meta:resourceKey="UmSellField">
<ItemStyle CssClass="alpha" />
<HeaderStyle CssClass="alpha" />
<ItemTemplate>
<asp:Label ID="UmSellLabel" runat="server" EnableViewState="false"
Text='<%# GetUnitOfMeasure(Container.DataItem,false) %>'>
</asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
codebehind
protected void SearchResults_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType.Equals(DataControlRowType.DataRow))
{
e.Row.Visible = showRow;
e.Row.Cells[0].Visible = showRow;
}
}
ShowRow is a boolean value that gets set in GetUnitOfMeasure function (not copied here) based on these conditions.

how to edit and update row values in grid view?

I have a gridview like this :
<asp:GridView ID="gvProducts" runat="server" AutoGenerateEditButton="True" AutoGenerateColumns="False"
OnRowEditing="gvProducts_RowEditing" OnRowUpdating="gvProducts_RowUpdating" CellPadding="4"
ForeColor="#333333" GridLines="None">
<RowStyle BackColor="#FFFBD6" ForeColor="#333333" />
<Columns>
<asp:TemplateField>
<HeaderTemplate>
<asp:Label ID="lblPID" runat="server" Text="Product ID"></asp:Label>
</HeaderTemplate>
<ItemTemplate>
<asp:Label ID="lblProdID" runat="server" Text='<%#Eval("ProductID")%>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="txtProdID" runat="server" Text='<%#Eval("ProductID")%>'></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<HeaderTemplate>
<asp:Label ID="lblPName" runat="server" Text="Product Name"></asp:Label>
</HeaderTemplate>
<ItemTemplate>
<asp:Label ID="lblProdName" runat="server" Text='<%#Eval("ProductName")%>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="txtProdName" runat="server" Text='<%#Eval("ProductName")%>'></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>
</Columns>
<FooterStyle BackColor="#990000" Font-Bold="True" ForeColor="White" />
<PagerStyle BackColor="#FFCC66" ForeColor="#333333" HorizontalAlign="Center" />
<SelectedRowStyle BackColor="#FFCC66" Font-Bold="True" ForeColor="Navy" />
<HeaderStyle BackColor="#990000" Font-Bold="True" ForeColor="White" />
<AlternatingRowStyle BackColor="White" />
</asp:GridView>
and here is the code behind page
protected void gvProducts_RowEditing(object sender, GridViewEditEventArgs e)
{
gvProducts.EditIndex = e.NewEditIndex;
}
protected void gvProducts_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
int i = e.RowIndex;
object control = gvProducts.Rows[i].FindControl("txtProdID");
//i want to access the new value from the object "control" but i m getting the previous value only
}
try this
protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
TextBox txtProdID = (TextBox)gvProducts.Rows[e.RowIndex].FindControl("txtProdID");
TextBox txtProdName = (TextBox)gvProducts.Rows[e.RowIndex].FindControl("txtProdName");
//Call update method
Product.Update(txtProdId,txtProdName);
gvProducts.EditIndex = -1;
//Refresh the gridviwe
BindGrid();
}
You need to check the e.NewValues dictionary for updated data.
I've a sample below, the GridView Template is bound to CategoryName.
OnRowUpdating is fired when the 'Edit' button is clicked.
In the RowUpdating event handler, it fetches the CategoryName data to which the textbox is bound to.
Note: Instead of using TextBox in normal mode use Labels.
<asp:GridView ID='GridView1' runat='server' DataKeyNames='CategoryID' OnRowUpdating='HandleOnGridViewRowUpdating'
DataSourceID='ObjectDataSource1' AutoGenerateColumns='false'>
<Columns>
<asp:CommandField ShowEditButton="true" />
<asp:TemplateField>
<HeaderTemplate>
<asp:Label ID='CategoryName' Text='Category' runat='server'></asp:Label>
</HeaderTemplate>
<ItemTemplate>
<asp:TextBox ID='CategoryNameTextbox' Text='<%# Bind("CategoryName") %>' runat='server'></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
code-behind:
public void HandleOnGridViewRowUpdating(object sender, GridViewUpdateEventArgs e)
{
if (e.NewValues["CategoryName"] != null)
{
String newCategoryName = e.NewValues["CategoryName"].ToString();
// process the data;
}
}

Categories