I have a table of users (and their info). I want to have a link so they could edit any given user. I realized that I couldn't use asp:button and asp:hyperlink controls because those controls won't show in the html table. I've tried
<a href="" runat="server" id="editBtn" onserverclick="editBtn_ServerClick">Edit</a>
But it won't fire anything in the function below
protected void editBtn_ServerClick(object sender, EventArgs e)
{
//stuff
}
I've tried creating a click event when my page loads (as suggested in another question on stackoverflow) but this too doesn't work...
HtmlAnchor HA = new HtmlAnchor();
HA.ServerClick = new EventHandler(editBtn_ServerClick);
I don't want to send the user to another page but I can't use asp:button to accomplish what I want so thus am using .
Any help would be greatly appreciated! Thank you in advance.
CodePudding user response:
Actually, you can most certainly pop up a dialog or some such to edit a given row.
And you can with ease drop in a plane jane button into that table, or in this case I suggest using a gridview, or even a listview (my favaorte).
so, lets do two simple things:
drop in a control to display our "table" or data. Then drop in a div to edit the data. That "div" will be what we pop up to edit that one row of "details" in a form like display (as opposed as you note trying to edit data "in place" in a row of data which is a poor UI).
So, say we have this markup for hte table (a grid view).
<asp:GridView ID="GridView1"
runat="server" CssClass="table" AutoGenerateColumns="false"
width="45%" DataKeyNames="ID" >
<Columns>
<asp:BoundField DataField="FirstName" HeaderText="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="LastName" />
<asp:BoundField DataField="HotelName" HeaderText="Hotel Name" />
<asp:BoundField DataField="Description" HeaderText="Description" ItemStyle-Width="270" />
<asp:TemplateField HeaderText="Edit">
<ItemTemplate>
<asp:Button ID="cmdEdit" runat="server" Text="Edit"
CssClass="btn" OnClick="cmdEdit_Click" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Note how in above we just dropped in a plain jane asp.net button to "edit" the data.
While you can just drag drop in the button from the toolbox, you can't double click on the button to create a click event, but you CAN in markup type in the onclick=
The instant you write "onclick=", (and hit the = button), then you get this in inteli-sense:
So, choose create event. After you do that, your button will show a plain jane click event, like this:
<asp:Button ID="cmdEdit" runat="server" Text="Edit"
CssClass="btn" OnClick="cmdEdit_Click" />
Might not seem like somthing occured, but we now have a simple click event wrired up and code behind will have such a code stub.
We go back to the above click event in a bit.
Ok, so now we need some code to load up the "table" (gridview).
That code is this:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadData();
}
void LoadData()
{
string strSQL = "SELECT * FROM tblHotelsA ORDER BY HotelName";
DataTable rstData = MyRst(strSQL);
GridView1.DataSource = rstData;
GridView1.DataBind();
}
public DataTable MyRst(string strSQL)
{
DataTable rstData = new DataTable();
using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
{
using (SqlCommand cmdSQL = new SqlCommand(strSQL, conn))
{
cmdSQL.Connection.Open();
rstData.Load(cmdSQL.ExecuteReader());
}
}
return rstData;
}
And now we see/have this:
Ok, next part:
We need to create a "edit" area on this page. A simple "div" with some text boxes etc. will suffice.
We ALSO need somthing to pop up the "edit area". There are oh so many choices, and since 99% of web sites already have jQuery, then addopting and adding jQuery.UI to our project is a good choice. You don't want to "roll your own" dialog or popup system when so many "great" choices exist.
So, we will assume jQuery, and jQuery.UI for this simple popup.
The next part is some markup in a div for editing the row. It can be anything quite much you cook up, but say for each hotel, I have all the details I want to edit. Place your markup in our div.
So, lets call the div "editrecord".
So, this:
<div id="EditRecord" runat="server" style="float: left; display: none; border: solid 2px; padding: 15px">
<style>
.iForm label {display: inline-block;width: 90px
}
.iForm input {border-radius: 8px;border-width: 1px;margin-bottom: 10px
}
.iForm textarea {border-radius: 8px;border-width: 1px;margin-bottom: 10px
}
.iForm input[type=checkbox] {
margin-right: 8px
}
</style>
<div style="float: left" >
<label>HotelName</label>
<asp:TextBox ID="txtHotel" runat="server" Width="280" />
<br />
<label>First Name</label>
<asp:TextBox ID="tFN" runat="server" Width="140" />
<br />
<label>Last Name</label>
<asp:TextBox ID="tLN" runat="server" Width="140" />
<br />
<label>City</label>
<asp:TextBox ID="tCity" runat="server" Width="140" />
<br />
<label>Province</label>
<asp:TextBox ID="tProvince" runat="server" Width="75"></asp:TextBox>
<br />
</div>
<div style="float: left; margin-left: 20px" >
<label>Description</label>
<br />
<asp:TextBox ID="txtNotes" runat="server" Width="400" TextMode="MultiLine"
Height="150px" f="Description"></asp:TextBox>
<br />
<asp:CheckBox ID="chkActive" Text=" Active" runat="server" TextAlign="Right" />
<asp:CheckBox ID="chkBalcony" Text=" Has Balcony" runat="server" TextAlign="Right" />
</div>
<div style="clear: both"></div>
<asp:Button ID="cmdSave" runat="server" Text="Save" CssClass="btn" />
<asp:Button ID="cmdCancel" runat="server" Text="Cancel" CssClass="btn" Style="margin-left: 10px" />
<asp:Button ID="cmdDelete" runat="server" Text="Delete" CssClass="btn" Style="margin-left: 20px" />
</div>
For now, lets just hide table, show edit div.
So,, our edit code becomes this:
protected void cmdEdit_Click(object sender, EventArgs e)
{
Button btn = sender as Button;
GridViewRow gRow = btn.NamingContainer as GridViewRow;
int PKID = (int)GridView1.DataKeys[gRow.RowIndex]["ID"];
string strSQL = "SELECT * FROM tblHotelsA WHERE ID = " PKID;
DataRow rstData = MyRst(strSQL).Rows[0];
txtHotel.Text = rstData["HotelName"].ToString();
tFN.Text = rstData["FirstName"].ToString();
tLN.Text = rstData["LastName"].ToString();
tCity.Text = rstData["City"].ToString();
tProvince.Text = rstData["Province"].ToString();
chkActive.Checked = (bool)rstData["Active"];
chkBalcony.Checked = (bool)rstData["Balcony"];
txtNotes.Text = rstData["Description"].ToString();
// hide table
GridView1.Style.Add("display", "none");
EditRecord.Style.Add("display", "nomral");
}
So, now we can click on any row, and the gv hides, and our edit area shows.
So, like this:
so, we can of course wire up the buttons to save.
but, the basic above approach quite much gets us our edit system, and one row click to launch edit for one row.
And assuming we have jQuery.UI installed?
Then we can change our edit button to not hide the table, but pop the above gv, and that code would look like:
So, we add this code to the client side:
<style>
.dialogWithDropShadow {
box-shadow: 10px 10px 10px rgba(0, 0, 0, 0.5);
}
</style>
<script>
function pophotel() {
var mydiv = $("#EditRecord")
mydiv.dialog({
modal: true, appendTo: "form",
title: "Edit Hotel", closeText: "",
width: "835px",
dialogClass: "dialogWithDropShadow"
});
}
function MyClose() {
popdiv = $('#EditRecord')
popdiv.dialog('close')
}
</script>
and our server side (to fill out the div) is now this:
protected void cmdEdit_Click(object sender, EventArgs e)
{
Button btn = sender as Button;
GridViewRow gRow = btn.NamingContainer as GridViewRow;
int PKID = (int)GridView1.DataKeys[gRow.RowIndex]["ID"];
string strSQL = "SELECT * FROM tblHotelsA WHERE ID = " PKID;
DataRow rstData = MyRst(strSQL).Rows[0];
txtHotel.Text = rstData["HotelName"].ToString();
tFN.Text = rstData["FirstName"].ToString();
tLN.Text = rstData["LastName"].ToString();
tCity.Text = rstData["City"].ToString();
tProvince.Text = rstData["Province"].ToString();
chkActive.Checked = (bool)rstData["Active"];
chkBalcony.Checked = (bool)rstData["Balcony"];
txtNotes.Text = rstData["Description"].ToString();
// pop the edit div using jQuery.UI dialog
Page.ClientScript.RegisterStartupScript(Page.GetType(), "MyJava", "pophotel()", true);
}
So, we now get/see this:
So, note some imporant things:
First up, we don't have to show, expose, or even in the markup hide the database PK "id". The datakeys feature allows us to NOT expose this information to the client side.
And on row click, then we get the index of the clicked row, and then grab the database row, and hten load our "div", and then pop that div.
Note how nice the jQuery.UI dialog is. It gray out the background, and that is a "modal" popup.
As noted, even if you don't adopt jQuery.UI, you can hide the grid, show the edit div, and on save button, save the data, hide the div, and show the gridview. So, the extra "bonus" part 2 with a cool popup is really optional, and does not change much how the code works.
Of course, I should post the "save" button code, and I will if you ask or wish to see how the save button code works.