I'm having trouble displaying a DataList in a aspx page.
protected void btnAdminExecuteQuery_Click(object sender, EventArgs e)
{
SqlDataAdapter _SqlDA;
try
{
_SqlConnection.Open();
_SqlCommand = new SqlCommand(txtBoxAdminQuery.Text, _SqlConnection);
_SqlDA = new SqlDataAdapter(_SqlCommand);
DataSet _SqlDS = new DataSet();
_SqlDA.Fill(_SqlDS);
_SqlConnection.Close();
DL.DataSource = _SqlDS.Tables[0];
DL.DataBind();
}
catch (Exception ex)
{
if (this._SqlConnection.State == ConnectionState.Open)
{
this._SqlConnection.Close();
}
txtBoxAdminErrorMsg.Text = ex.Message;
}
}
I'm sure the ConnectionString and command are correct because I've tested them, and I can see in the debugger that the DataList has rows, it has Data but it's just not displaying.
This is what I see when I execute the query on the 'Admin Panel'
HTML:
<asp:TextBox ID="txtBoxAdminQuery" runat="server" TextMode="MultiLine"></asp:TextBox>
<asp:Button ID="btnAdminExecuteQuery" runat="server" OnClick="btnAdminExecuteQuery_Click" Text="Execute Query" />
<asp:TextBox ID="txtBoxAdminErrorMsg" runat="server" Enabled="False" Height="68px" ReadOnly="True" TextMode="MultiLine" Width="463px"></asp:TextBox>
<asp:SqlDataSource ID="_SqlDS" runat="server" ConnectionString="<%$ ConnectionStrings:CompanyConnectionString %>" SelectCommand="SELECT * FROM [Accounts]"></asp:SqlDataSource>
<asp:DataList ID="DL" runat="server" CellPadding="1" CellSpacing="1" RepeatColumns="2">
</asp:DataList>
</div>
</form>
My goal is to run custom queries and display the results in the DataList, I know how to configure the DataList through Visual Studio Designer, but if I do it from there the Query is static I can't change it, as far as I know.
Proving that the _SqlDS has data:
Related
I have just a simple message page which consists of From: Text: and a Submit button, then I have another page, which contains nothing, it's my "Message Board" the most recent posted message goes on top of the board, both are aspx pages with master page.
I have a SQL DB, I'm already assuming there will be a table with From: Message:(with varchar i think), but what i don't understand how it will get inserted into the messageboard page in a most recent to oldest list fashion.
Message.aspx - From: Text: Submit
MessageBoard.aspx - just a div , messages submitted will appear here in a drop down list
I want it to be super simple no cool features, only "Submit the message" -> "Appears on MessageBoard.aspx to everyone",
and that's it
Ok, there are seveal moving parts.
Assuming you have SQL server running. Assuming you have a valid conneciton?
Ok, then on the post a new message page, you have this markup:
<h3>Post a message</h3>
<h4>enter your name</h4>
<asp:TextBox ID="txtName" runat="server" Width="250px"></asp:TextBox>
<br />
<h4>Enter your message</h4>
<asp:TextBox ID="txtMsg" runat="server" Height="185px" Width="520px"
TextMode="MultiLine" Font-Size="Large" style="border-radius:20px;border:solid 2px"
></asp:TextBox>
<br />
<br />
<asp:Button ID="cmdNewMessage" runat="server" Text="Post Message" CssClass="btn"
OnClick="cmdNewMessage_Click" />
And code behind looks like this:
protected void Page_Load(object sender, EventArgs e)
{
}
protected void cmdNewMessage_Click(object sender, EventArgs e)
{
string strSQL =
#"INSERT INTO tblMessages (UName, Message, MessageDate)
VALUES (#UName, #Message, #MessageDate)";
using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
{
using (SqlCommand cmdSQL = new SqlCommand(strSQL, conn))
{
conn.Open();
cmdSQL.Parameters.Add("#UName", SqlDbType.NVarChar).Value = txtName.Text;
cmdSQL.Parameters.Add("#Message",SqlDbType.NVarChar).Value = txtMsg.Text;
cmdSQL.Parameters.Add("#MessageDate", SqlDbType.NVarChar).Value = DateTime.Now;
cmdSQL.ExecuteNonQuery();
}
}
Response.Redirect("MessageBoard.aspx");
}
So, it looks like this:
when you hit post message, we jump to this page, and markup:
<asp:Button ID="cmdPost" runat="server"
Text="Post a new message"
CssClass="btn" OnClick="cmdPost_Click" />
<br />
<br />
<h2>Messages</h2>
<asp:GridView ID="GridView1" runat="server" Width="50%"
AutoGenerateColumns="False" DataKeyNames="ID" >
<Columns>
<asp:BoundField DataField="UName" HeaderText="Posted by" />
<asp:BoundField DataField="MessageDate" HeaderText="At" ItemStyle-Width="180px" />
<asp:TemplateField HeaderText="Message" >
<ItemTemplate>
<asp:Textbox ID="txtMsg" runat="server" TextMode="MultiLine" Width="100%"
Text='<%# Eval("Message") %>'
Height='<%# (Regex.Matches(Eval("Message").ToString() , System.Environment.NewLine).Count + 1) * 30 %>'
>
</asp:Textbox>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
And code is:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadGrid();
}
void LoadGrid()
{
using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
{
string strSQL = "SELECT * FROM tblMessages ORDER BY MessageDate DESC";
using (SqlCommand cmdSQL = new SqlCommand(strSQL, conn))
{
conn.Open();
GridView1.DataSource = cmdSQL.ExecuteReader();
GridView1.DataBind();
}
}
}
protected void cmdPost_Click(object sender, EventArgs e)
{
Response.Redirect("NewMessage.aspx");
}
And we now see/have this:
You don't explain what you mean by "what i don't understand how it will get inserted into the messageboard page in a most recent to oldest list fashion", so I can only guess.
When a new message is posted, you insert it into the database, including a DateTime column. Your message list page then just grabs the latest nn messages, ordered by newest first.
I'm assuming that you know how to do that. If not, do some reading about Entity Framework Core, as that provides a very good way of handling databases.
So, in princple, your question is no more complex than that. However, there are many variations on this, such as having the message list updated in real time, for which you should use SignalR, but without more specific explanation of what you want, it's hard to make any suggestions.
I have a repeater that I populate from a database:
using (SqlConnection conn = new SqlConnection(connString))
{
SqlCommand cmd = new SqlCommand(#"SELECT CommunityName, CID, Budget FROM Donation WHERE Year = year(getdate()) ORDER BY CommunityName", conn);
conn.Open();
SqlDataAdapter adp = new SqlDataAdapter(cmd);
DataSet myDataSet = new DataSet();
adp.Fill(myDataSet);
myRep.ItemDataBound += new RepeaterItemEventHandler(myRep_ItemDataBound);
myRep.DataSource = myDataSet;
myRep.DataBind();
}
void myRep_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
var textbox = e.Item.FindControl("community");
textbox.ClientIDMode = ClientIDMode.Static;
textbox.ID = "community" + (e.Item.ItemIndex + 1);
}
Repeater:
<asp:UpdatePanel ID="UpdatePanel" runat="server" UpdateMode="Always">
<ContentTemplate>
<asp:Repeater ID="myRep" runat="server">
<ItemTemplate>
<div class="form-group">
<asp:Label ID='thisLbl' runat="server" Text='<%# Eval("CommunityName") %>' />
<asp:TextBox runat="server" ID="community" Text='<%# Eval("Budget") %>' CssClass="form-control" />
</div>
</ItemTemplate>
</asp:Repeater>
</ContentTemplate>
</asp:UpdatePanel>
This creates 6 textboxes with labels and values, now my question is how do I detect which of these boxes belongs to the record it was initially pulled from in the database? I want to be able to modify the value in these boxes and hit a button to save them back to the database but I can't seem to wrap my head around getting them to the proper records.
Should I set the ID of the textbox to something I can parse through and match with the proper record? In the ItemDataBound?
You have to put a hidden field inside the repeater item template that takes the value from budget, and another hidden field to keep the CID value that has to be read in the post back request. Of course you need also a button and its click event handler.
<asp:Repeater ID="myRep" runat="server">
<ItemTemplate>
<div class="form-group">
<asp:Label ID='thisLbl' runat="server" Text='<%# Eval("CommunityName") %>' />
<asp:TextBox runat="server" ID="txtBudget" Text='<%# Eval("Budget") %>' CssClass="form-control" />
<asp:HiddenField runat="server" ID="hdOriginalBudget" Value='<%# Eval("Budget") %>' />
<asp:HiddenField runat="server" ID="hdCID" Value='<%# Eval("CID") %>' />
</div>
</ItemTemplate>
</asp:Repeater>
<br />
<asp:Button ID="btn" runat="server" OnClick="btn_Click" />
In your code behind you need to loop inside the repeater to check whether the text box has been changed by comparing its value to the hidden field. After you save the budget value in the database you need to realign the hidden field value to the the new value entered by the user, otherwise you will always save that value after each post back:
protected void btn_Click(object sender, EventArgs e)
{
foreach (RepeaterItem item in myRep.Items)
{
var txtBudget = item.FindControl("txtBudget") as TextBox;
var hdOriginalBudget = item.FindControl("hdOriginalBudget") as HiddenField;
var hdCID = item.FindControl("hdCID") as HiddenField;
if (txtBudget.Text != hdOriginalBudget.Value)
{
//If you enter here means the user changed the value of the text box
using (SqlConnection conn = new SqlConnection(connString))
{
SqlCommand cmd = new SqlCommand(#"UPDATE Donation SET Budget = #Budget WHERE CID = #CID", conn);
cmd.Parameters.Add(new SqlParameter("#Budget", int.Parse(txtBudget.Text)));
cmd.Parameters.Add(new SqlParameter("#CID", int.Parse(hdCID.Value)));
conn.Open();
cmd.ExecuteNonQuery();
}
//After you write in the database realign the values
hdOriginalBudget.Value = txtBudget.Text;
}
}
}
Take care that my code is missing the most basic validation, so if the user writes an invalid value in the textbox (for example "yyy") it breaks. So please don't put it in production as it is!
I am creating the update button for the cart system in asp.net. What am I trying to do is to allow user key in the quantity items and then click the update button. Here is the design of the shopping cart system...
Unfortunately the update button doesn't work properly after the first row. I have debugged the problem and the for loop inside the btn_update_Click method returns the value of zero.
Is there any other way to overcome the problem? Thanks
Here is the source code:
<b><asp:Label ID="lbl_showResult" runat="server" Text=""></asp:Label></b>
<asp:GridView ID="grv_cart" runat="server" AllowPaging="True" AutoGenerateColumns="False" DataSourceID="sds_store" ShowHeader="True" GridLines="None" CssClass="table">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<a class="hyp_productimage imgLiquidFill imgLiquid productImage img-responsive" href='<%# string.Format("product.aspx?ProductID={0}", Eval("product_id")) %>'>
<img src='<%#Eval("image") %>' />
</a>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Product">
<ItemTemplate>
<asp:Hyperlink ID="hyp_productname" Text='<%# Eval("product_name") %>' runat="server" NavigateUrl='<%# string.Format("product.aspx?ProductID={0}", Eval("product_id")) %>'></asp:Hyperlink>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Quantity">
<ItemTemplate>
<asp:TextBox ID="txt_productQuantity" Text='<%# Eval("product_quantity") %>' CssClass="form-control" runat="server" Width="60" MaxLength="5"></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:Button ID="btn_update" Text="Update" runat="server" CommandArgument='<%# Eval("id") %>' CssClass="btn btn-warning" OnClick="btn_update_Click" />
<asp:Button ID="btn_remove" Text="Delete" runat="server" CommandArgument='<%# Eval("id") %>' CssClass="btn btn-danger" onclick="btn_remove_Click"/>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Cost">
<ItemTemplate>
<asp:Hyperlink ID="hyp_productcost" Text='<%#"$"+Eval("product_cost") %>' runat="server" NavigateUrl='<%# string.Format("product.aspx?ProductID={0}", Eval("product_id")) %>'></asp:Hyperlink>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="sds_store" runat="server"
ConnectionString="<%$ ConnectionStrings:websiteConnection %>"
SelectCommand="SELECT [id], [product_id], [product_name], [product_cost], [product_description], [product_quantity], [image], [date] FROM [tbl_cart] WHERE [name] = #username AND [visible] = #visible">
<SelectParameters>
<asp:sessionparameter sessionfield="login" Name="username" />
<asp:Parameter Name="visible" Type="string" DefaultValue="true" />
</SelectParameters>
</asp:SqlDataSource>
<h4><asp:Label ID="lbl_totalCost" Text="" runat="server" CssClass="pull-right"></asp:Label></h4>
<br /><br /><br />
<asp:Button ID="btn_buy" Text="Buy Now" runat="server" CssClass="btn btn-success btn-lg pull-right" OnClick="btn_buy_Click" />
Here's another source code for the .cs:
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace websiteEcom
{
public partial class cart : System.Web.UI.Page
{
// Open the connection for the sql
private static SqlConnection conn;
private static SqlCommand command;
protected void Page_Load(object sender, EventArgs e)
{
// Create an instance for the connection of database
string connectionString = ConfigurationManager.ConnectionStrings["websiteConnection"].ToString();
conn = new SqlConnection(connectionString);
command = new SqlCommand("", conn);
// Checks how many items are there inside the cart database and display it to the label
CheckHowManyItem();
// Multiply all the sums of the cost
lbl_totalCost.Text = "Total Cost: $"+TotalProductCost().ToString();
}
// Checks how many items are there inside the cart database and display it to the label
public void CheckHowManyItem()
{
try
{
conn.Open();
// Retrieve the number of rows from the database
string query = string.Format("SELECT COUNT(*) FROM tbl_cart WHERE name = '{0}' AND visible = '{1}'", Session["login"], "true");
command.CommandText = query;
int numberOfItems = (int)command.ExecuteScalar();
// If the number of rows is zero
if (numberOfItems == 0)
{
lbl_showResult.Text = "You have no items inside the cart.";
btn_buy.Visible = false;
}
else
{
// If there is number of rows inside
lbl_showResult.Text = "There are currently " + numberOfItems + " inside the cart.";
btn_buy.Visible = true;
}
}
finally
{
conn.Close();
}
}
protected void btn_remove_Click(object sender, EventArgs e)
{
// Get the value from the button ASP.NET gridview
Button btn = (Button)sender;
try
{
conn.Open();
// Make the cart invisible if the id matches with the grid view data source
string query = string.Format("UPDATE tbl_cart SET visible = '{0}' WHERE id = '{1}'", "false", btn.CommandArgument);
command.CommandText = query;
command.ExecuteNonQuery();
Response.Redirect("cart.aspx");
}
finally
{
conn.Close();
}
}
// Multiply all the values of purchases together
public int TotalProductCost()
{
int totalCost = 0;
int currentCost = 0;
int currentQuantity = 0;
for (int i = 0; i < grv_cart.Rows.Count; i++)
{
// Get the data values from the forms
HyperLink hypCost = (HyperLink)grv_cart.Rows[i].Cells[0].FindControl("hyp_productcost");
TextBox txtQuantity = (TextBox)grv_cart.Rows[i].Cells[0].FindControl("txt_productQuantity");
// Sum the product quantity and the product cost
// Attempt to parse your value (removing any non-numeric values)
currentQuantity = Int32.Parse(Regex.Replace(txtQuantity.Text, #"[^\d]", ""));
// Attempt to parse your value (removing any non-numeric values)
currentCost = Int32.Parse(Regex.Replace(hypCost.Text, #"[^\d]", ""));
currentCost *= currentQuantity;
totalCost += currentCost;
}
return totalCost;
}
protected void btn_buy_Click(object sender, EventArgs e)
{
}
protected void btn_update_Click(object sender, EventArgs e)
{
// Get the value from the button ASP.NET gridview
Button btn = (Button)sender;
foreach (GridViewRow grvCart in grv_cart.Rows)
{
Debug.WriteLine(btn.CommandArgument);
TextBox textQuantity = (TextBox)grvCart.FindControl("txt_productQuantity");
int currentQuantity = Int32.Parse(Regex.Replace(textQuantity.Text, #"[^\d]", ""));
try
{
conn.Open();
// Update the cart quantity if the id matches with the grid view data source
string query = string.Format("UPDATE tbl_cart SET product_quantity = '{0}' WHERE id = '{1}'", currentQuantity, btn.CommandArgument);
command.CommandText = query;
command.ExecuteNonQuery();
Response.Redirect("cart.aspx");
}
finally
{
conn.Close();
}
}
}
}
}
Try using the RowCommand event (especially since you already have the CommandArgument set up). That is the more appropriate way to handle this type of action (and that way you can just update one row at a time, without looping through all of them).
Handle the RowCommand event in your GridView declaration:
<asp:GridView ID="grv_cart" runat="server" AllowPaging="True"
AutoGenerateColumns="False" DataSourceID="sds_store" ShowHeader="True"
GridLines="None" CssClass="table" OnRowCommand="grv_cart_RowCommand">
And then your event handler would look like this:
protected void grv_cart_RowCommand(Object sender, GridViewCommandEventArgs e)
{
GridViewRow rowToUpdate = grv_cart.Rows[Int.Parse(e.CommandArgument)];
TextBox textQuantity = (TextBox)rowToUpdate.FindControl("txt_productQuantity");
int currentQuantity = Int32.Parse(Regex.Replace(textQuantity.Text, #"[^\d]", ""));
try
{
conn.Open();
// Update the cart quantity if the id matches with the grid view data source
string query = string.Format("UPDATE tbl_cart SET product_quantity = '{0}' WHERE id = '{1}'", currentQuantity, e.CommandArgument);
command.CommandText = query;
command.ExecuteNonQuery();
Response.Redirect("cart.aspx");
}
finally
{
conn.Close();
}
}
Note: You'll want to remove the OnClick handler from the update button:
<asp:Button ID="btn_update" Text="Update" runat="server"
CommandArgument='<%# Eval("id") %>' CssClass="btn btn-warning" />
I am having a problem with gridviews. Basically I am writing an aircraft information and tracking system and in the process getting to know the wonders of gridviews, but I have trouble with adding a new row to the gridview. I am able to create a new row to input the data when a button is pressed, but when I click on update, I am having some sort of postback problem that is causing that data to be forgotten and can't find a way around it. The datasource is a list of cargodoor objects that contain doubles and strings holding measurements, names etc. Here is my code.
<asp:UpdatePanel ChildrenAsTriggers="true" ID="UpdatePanel2" runat="server">
<ContentTemplate>
<div id="divAddCargoDoor" style="width:100%" runat="server" class="AlignRight">
<asp:LinkButton ID="lbAddNewCargoDoor" runat="server"
Text="<%$ Resources:ls, AddCargoDoor %>"
OnClick="lbAddNewCargoDoor_Click"></asp:LinkButton><br /><br />
</div>
<div id="divCargoDoorNoDoors" runat="server">
<asp:Label ID="lCargoDoorNoDoors" runat="server"
Text="<%$ Resources:ls, NoCargoDoors %>"></asp:Label>
</div>
<asp:GridView ID="gvCargoDoors" runat="server" AutoGenerateColumns="False"
DataKeyNames="Id" Width="100%"
OnRowEditing="gvCargoDoors_RowEditing"
OnRowUpdating="gvCargoDoors_RowUpdating"
OnRowDeleting="gvCargoDoors_RowDeleting"
OnRowCancelingEdit="gvCargoDoors_RowCancellingEdit">
<Columns>
<asp:CommandField AccessibleHeaderText="Edit" ShowEditButton="True" />
<asp:TemplateField AccessibleHeaderText="Name"
HeaderText="<%$ Resources:ls, Description %>">
<ItemTemplate>
<asp:Label ID="lName" runat="server" Text='<%# Bind("Name") %>' />
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="Name" runat="server" Text='<%# Bind("Name") %>' />
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField AccessibleHeaderText="Width"
HeaderText="<%$ Resources:ls, Width %>">
<ItemTemplate>
<asp:Label ID="lWidth" runat="server" Text='<%# Bind("Width") %>' />
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="CDWidth" runat="server" Text='<%# Bind("Width") %>' />
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField AccessibleHeaderText="Height"
HeaderText="<%$ Resources:ls, Height %>">
<ItemTemplate>
<asp:Label ID="lHeight" runat="server" Text='<%# Bind("Height") %>' />
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="CDHeight" runat="server" Text='<%# Bind("Height") %>' />
</EditItemTemplate>
</asp:TemplateField>
<asp:CommandField AccessibleHeaderText="Delete" ShowDeleteButton="True"
DeleteText="X" />
</Columns>
</asp:GridView>
<br />
</ContentTemplate>
</asp:UpdatePanel>
Now for the C# code
First we have this piece that gets the information from the database that is used to build the datasource. It calls a simple sql database call to the SQL Server 2008 database and returns the data in an aircraft object, that contains a list of cargodoor objects.
private void BuildDataSource()
{
this.ac = Charter.Aircraft.Retrieve(Convert.ToInt32(this.hfAircraftID.Value));
}
Now here is the code for the actual cargo door controls
private void BindCargoDoors()
{
if (ac.CargoDoors.Count == 0)
{
//display a label telling user there are no cargo doors
divCargoDoorNoDoors.Visible = true;
}
else
{
//bind the cargodoor object list to the gridview
divCargoDoorNoDoors.Visible = false;
this.gvCargoDoors.DataSource = this.ac.CargoDoors;
this.gvCargoDoors.DataBind();
}
}
protected void gvCargoDoors_RowEditing(object sender, GridViewEditEventArgs e)
{
//get the index of the row and enter row editing mode
this.gvCargoDoors.EditIndex = e.NewEditIndex;
BuildDataSource();
BindCargoDoors();
}
protected void gvCargoDoors_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
//get the row being edited
GridViewRow row = this.gvCargoDoors.Rows[e.RowIndex];
//create a new cargo door to store the info in
CargoDoor cd = new CargoDoor();
//Retrieve the id of the cargodoor
cd.Id = Convert.ToInt32(gvCargoDoors.DataKeys[e.RowIndex].Values["Id"]);
if (cd.Id == 0) //will apply when new cargodoor is added
{
//fill in the cargodoor object from data in the row
cd.DateAdded = DateTime.Now;
cd.DateModified = DateTime.Now;
cd.Name = ((TextBox)row.FindControl("Name")).Text;
cd.Width = Convert.ToDouble(((TextBox)row.FindControl("Width")).Text);
cd.Height = Convert.ToDouble(((TextBox)row.FindControl("Height")).Text);
cd.Owner = this.ac.Owner;
cd.AircraftId = this.ac.Id;
//insert the new cargodoor into the database
Charter.Aircraft.InsertCargoDoor(cd);
}
else
{
//Retrieve old cargodoor info and fill in object info into cd
CargoDoor cdOrig = Charter.Aircraft.RetrieveCargoDoorByID(cd.Id);
//fill in the cargodoor object with retrieved info
cd.AircraftId = cdOrig.AircraftId;
cd.DateAdded = cdOrig.DateAdded;
cd.Notes = cdOrig.Notes;
cd.Owner = cdOrig.Owner;
//fill in updated information
cd.Name = ((TextBox)row.FindControl("Name")).Text;
cd.Width = Convert.ToInt32(((TextBox)row.FindControl("Width")).Text);
cd.Height = Convert.ToInt32(((TextBox)row.FindControl("Height")).Text);
cd.DateModified = DateTime.Now;
//save the new cargodoor info
Charter.Aircraft.UpdateCargoDoor(cd);
}
//rebuild data source to get new cargo door
BuildDataSource();
//Reset the edit index.
this.gvCargoDoors.EditIndex = -1;
//Bind data to the GridView control.
BindCargoDoors();
}
protected void gvCargoDoors_RowCancellingEdit(object sender,
GridViewCancelEditEventArgs e)
{
this.gvCargoDoors.EditIndex = -1;
BuildDataSource();
BindCargoDoors();
}
protected void gvCargoDoors_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
BuildDataSource();
int id = Convert.ToInt32(gvCargoDoors.DataKeys[e.RowIndex].Values["Id"]);
Charter.Aircraft.DeleteCargoDoor(id);
BuildDataSource();
BindCargoDoors();
}
protected void lbAddNewCargoDoor_Click(object sender, EventArgs e)
{
//trigger the edit mode with an edit row index of 0
this.gvCargoDoors.SetEditRow(0);
//insert a new cargodoor into the source object
this.ac.CargoDoors.Insert(0, new CargoDoor());
//bind the data
this.gvCargoDoors.DataSource = this.ac.CargoDoors;
BindCargoDoors();
}
My big problem is to do with the lbAddNewCargoDoor and the editing of a row. When the update link is pressed it has forgotten that a new row was added and so just edits the row that already exists, rather than inserting a new cargodoor object into the database. I am just not sure on the order of operations to prevent this from screwing up.
Any help would be appreciated. Thanks.
try changing (see the change in order of statements)
protected void lbAddNewCargoDoor_Click(object sender, EventArgs e)
{
//trigger the edit mode with an edit row index of 0
this.gvCargoDoors.SetEditRow(0);
//insert a new cargodoor into the source object
this.ac.CargoDoors.Insert(0, new CargoDoor());
//bind the data
this.gvCargoDoors.DataSource = this.ac.CargoDoors;
BindCargoDoors();
}
to
protected void lbAddNewCargoDoor_Click(object sender, EventArgs e)
{
//insert a new cargodoor into the source object
this.ac.CargoDoors.Insert(0, new CargoDoor());
//bind the data
this.gvCargoDoors.DataSource = this.ac.CargoDoors;
//trigger the edit mode with an edit row index of 0
this.gvCargoDoors.SetEditRow(0);
BindCargoDoors();
}
Please note that I cannot add comments (due to less reputation) and I am aware that this should be a comment.
Recent problems I've had are making me question my whole philosophy and assumptions regarding GridViews.
Currently, I have used something along the lines of the following model.
In Markup:
<asp:UpdatePanel ID="pnlSearch" UpdateMode="Conditional" runat="server">
<ContentTemplate>
<asp:TextBox ID="txtSearch" runat="server"
ontextchanged="txtSearch_TextChanged"></asp:TextBox>
</ContentTemplate>
</asp:UpdatePanel>
<asp:UpdatePanel ID="pnlGridView" UpdateMode="Conditional" runat="server">
<ContentTemplate>
<asp:GridView ID="GridView1" EnableViewState="false" AllowPaging="true" PageSize="20" DataSourceID="MyDataSource" runat="server" AutoGenerateColumns="False">
<Columns>
<asp:BoundField DataField="COL_1" HeaderText="Happy Data" SortExpression="COL_1" />
<asp:BoundField DataField="COL_2" HeaderText="Happy Related Data" SortExpression="COL_2" DataFormatString="{0:M/dd/yyyy}" />
</Columns>
</asp:GridView>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="txtSearch" EventName="TextChanged" />
</Triggers>
</asp:UpdatePanel>
<asp:SqlDataSource ID="MyDataSource" runat="server"></asp:SqlDataSource>
Pretty basic stuff. A GridView. A data source. A text box for searching results. I include the UpdatePanels only because I'm somewhat convinced they could be part of my problems.
Over in my code behind, I usually would do something like this:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
MyDataSource.ConnectionString = ConfigurationManager.ConnectionStrings["OracleConnectionString"].ConnectionString;
MyDataSource.ProviderName = ConfigurationManager.ConnectionStrings["OracleConnectionString"].ProviderName;
GridView1.EmptyDataText = "No comments found.";
PopulateGridView();
}
}
protected void PopulateGridView()
{
string strQuery = #"SELECT COL_1,
COL_2
FROM some_table
WHERE COL_3 = :important_filter";
MyDataSource.SelectCommand = strQuery;
MyDataSource.SelectParameters.Clear();
MyDataSource.SelectParameters.Add(":important_filter", Request.QueryString["filter"]);
GridView1.DataBind();
GridView1.PageIndex = 0;
}
protected void txtSearch_TextChanged(object sender, EventArgs e)
{
string strQuery = #"SELECT COL_1,
COL_2
FROM some_table
WHERE COL_3 = :important_filter AND lower(COL_2) LIKE :search";
MyDataSource.SelectCommand = strQuery;
MyDataSource.SelectParameters.Clear();
MyDataSource.SelectParameters.Add(":important_filter", Request.QueryString["filter"]);
MyDataSource.SelectParameters.Add(":search", "%" + txtSearch.Text.Trim().ToLower() + "%");
GridView1.DataBind();
GridView1.PageIndex = 0;
}
Nothing too fancy. I initially connect up the data source to a connection string from the config file (as is necessary in a multi instance environment), wire up the query and databind. On searches, I change the query and rebind.
The only problem?
The above doesn't work. Why? The data source loses it's query, connection string, provider name, etc on post back. So the gridview commits suicide. The same thing happens when I try to change pages...either on initial load or with a search populated.
I "solved" this problem last week by manually adding the datasource to control state and repopulating the values from control state, but that seems hackish.
What am I not understanding?
You have the update mode set to conditional so you need to call update on 'pnlGridView'
GridView1.DataBind();
GridView1.PageIndex = 0;
pnlGridView.Update();
I would also revist how you are using your DataSource
<asp:SqlDataSource ID="ProductsDataSource" runat="server"
ConnectionString="<%$ ConnectionStrings:OracleConnectionString %>"
SelectCommand="SELECT COL_1, COL_2 FROM some_table WHERE COL_3 = #important_filter">
<SelectParameters>
<asp:ControlParameter ControlID="textBox?not sure where this is coming from" PropertyName="SelectedValue" Name="important_filter" Type="string" DefaultValue="" />
</SelectParameters>
</asp:SqlDataSource>
You could also use a server side event handler and set the important filter manually.
protected void SQLDataSource_Selecting(object sender, SQLDataSourceSelectingEventArgs e) {
e.InputParameters["important_filter"] = "whatever";
}
And add the event to your markup for your SQLDataSource.
<asp:SqlDataSource ID="MyDataSource" runat="server" OnSelecting="SQLDataSource_Selecting" />