Ok, so the approach here, and how you want this to look?
Well, you really have near unlimited choices here. Some like to display the main record, and then popup a search edit. Some like to display a grid, and then the user clicks on one row to edit, and then we popup a form to edit the record (and in your question, also allow uploading of files).
The first suggestion is to find and adopt a good popup library. I had great success using the dialog from jQuery.UI. So, I will assume that you have both jQuery, and jQuery.UI installed for this to work.
The next issue of course is uploading files. I recommend using a good quality up-loader control, and one that allows say multiple files, works in a update panel, and one that does not require a post-back for each file uploaded. There are many such uploaders available, but I using the AjaxFileUploader from the ajax tool kit.
So, say we have a simple GridView with this markup:
<asp:GridView ID="GridView1"
runat="server" CssClass="table table-hover" AutoGenerateColumns="false"
width="48%" DataKeyNames="ID" OnRowDataBound="GridView1_RowDataBound" >
<Columns>
<asp:BoundField DataField="FirstName" HeaderText="First Name" />
<asp:BoundField DataField="LastName" HeaderText="Last Name" />
<asp:BoundField DataField="HotelName" HeaderText="Hotel Name" ItemStyle-Width="160" />
<asp:BoundField DataField="Description" HeaderText="Description" ItemStyle-Width="270" />
<asp:TemplateField HeaderText="Edit" ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:LinkButton ID="cmdEdit" runat="server"
class="btn myshadow"
OnClick="cmdEdit_Click" >
<span aria-hidden="true" class="glyphicon glyphicon-floppy-saved"> Edit</span>
</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Ok, now the code to load above, rather simple:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadData();
}
void LoadData()
{
string strSQL = "SELECT * FROM tblHotelsA ORDER BY HotelName";
DataTable rstData = General.MyRst(strSQL);
GridView1.DataSource = rstData;
GridView1.DataBind();
}
And now the result looks like this:
So, now we need to wire up the edit button.
As noted, we will use a jQuery.UI dialog.
So, when we click a row, we load up the markup with the one record. I'll not post all of the markup, but the jQuery.UI dialog pops a div on the page.
So, I have this markup:
<div id="EditRecord" runat="server"
style="float:left;padding:15px;display:none">
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:RadioButtonList ID="RBmenu" runat="server" RepeatDirection="Horizontal"
CssClass="rMyChoice"
AutoPostBack="true"
OnSelectedIndexChanged="RBmenu_SelectedIndexChanged"
>
<asp:ListItem Selected="True">Edit Hotel</asp:ListItem>
<asp:ListItem>Upload Files</asp:ListItem>
</asp:RadioButtonList>
<br />
<div id="hoteltab" runat="server">
<div style="float: left" class="iForm">
<label>HotelName</label>
<asp:TextBox ID="txtHotel" runat="server" Width="280" f="HotelName" /><br />
<label>First Name</label>
<asp:TextBox ID="tFN" runat="server" Width="140" f="FirstName" /><br />
<label>Last Name</label>
<asp:TextBox ID="tLN" runat="server" Width="140" f="LastName" ClientIDMode="Static" /><br />
<label>City</label>
<asp:TextBox ID="tCity" runat="server" Width="140" f="City" ClientIDMode="Static" /><br />
<label>Province</label>
<asp:TextBox ID="tProvince" runat="server" Width="75" f="Province" /><br />
</div>
I have not posted all the markup, but the concept is a simple div, and inside I placed a update panel, since in "genreal", any post-back will collopse such dialogs. However, introduction of a update panel means the popup can have postbacks and remain open.
So, the row edit button click looks like this:
protected void cmdEdit_Click(object sender, EventArgs e)
{
LinkButton btn = sender as LinkButton;
GridViewRow gRow = btn.NamingContainer as GridViewRow;
int PKID = (int)GridView1.DataKeys[gRow.RowIndex]["ID"];
Session["PKID"] = PKID;
string strSQL = $"SELECT * FROM tblHotelsA WHERE ID = {PKID}";
DataRow rstData = General.MyRst(strSQL).Rows[0];
General.FLoader(this.hoteltab, rstData);
LoadPictures(PKID);
string sJava = $"pophotel('{btn.ClientID}');";
ScriptManager.RegisterStartupScript(this.Page, Page.GetType(), "mypopedit", sJava, true);
}
So, we get the current row database PK value. We load up our simple markup with the record (floader), and then we pop the div by injecting JavaScript into the page.
The resulting effect is this:
So, not a lot of code so far. The code to save the record being edited is this:
protected void cmdSave_Click(object sender, EventArgs e)
{
int PKID = (int)Session["PKID"];
General.FWriter(this.hoteltab, PKID, "tblHotelsA");
LoadData(); // re-load grid to show any changes
}
But, if you look close at the save button, I have both a client side code stub (to close the dialog), and then the above code to write the changes back to the database, and then I re-load the grid to show any edits/changes done.
so, that save button markup looks like this:
<asp:LinkButton ID="cmdSave" runat="server" class="btn myshadow"
OnClick="cmdSave_Click"
OnClientClick="MyClose();">
<span aria-hidden="true" class="glyphicon glyphicon-floppy-saved">Save</span>
</asp:LinkButton>
And the client side JavaScript again is not much. This:
<script>
function pophotel(btnT) {
var btn = $('#' + btnT)
var mydiv = $("#EditRecord")
var target = $(this)
mydiv.dialog({
modal: true, appendTo: "form",
title: "Edit Hotel", closeText: "",
width: "85%",
dialogClass: "dialogWithDropShadow",
position: { my: 'top+40', at: 'top', of: target }
});
}
function MyClose() {
popdiv = $('#EditRecord')
popdiv.dialog('close')
}
function alldone() {
// runs when all files uploaded.
$('#cmdAllDone').click()
}
</script>
The uploader code (that allows multiple pictures to be up-loaded) is this:
protected void AjaxFileUpload1_UploadComplete(object sender, AjaxControlToolkit.AjaxFileUploadEventArgs e)
{
int PKID = (int)Session["PKID"];
// append database pk so no collsion occures for uploaded file names
string sUFile =
$"{Path.GetFileNameWithoutExtension(e.FileName)}{PKID.ToString()}" +
Path.GetExtension(e.FileName);
string sFile =
Server.MapPath($@"~/Content/Hotels/{sUFile}");
AjaxFileUpload1.SaveAs(sFile);
string strSQL =
@"INSERT INTO tblHotelPictures (Hotel_ID, FileName, UpLoaded)
VALUES (@Hotel_ID, @FileName, @UpLoaded)";
SqlCommand cmdSQL = new SqlCommand(strSQL);
cmdSQL.Parameters.Add("@Hotel_ID",SqlDbType.Int).Value = PKID;
cmdSQL.Parameters.Add("@FileName",SqlDbType.NVarChar).Value = sUFile;
cmdSQL.Parameters.Add("@UpLoaded",SqlDbType.DateTime).Value = DateTime.Now;
General.MyRstE(cmdSQL);
}
So, the above should give some ideas here as to how to allow a popup row edit, but also allow uploading of files in that dialog. I used a raditobutton list for my "menu" that allows ones to toggle between up-loading and editing. I suppose you could use some kind of fancy tab control, but I just used 2 div, and hide/show either div based on what radiobutton is selected.
All in all, not a lot of code was written here, but that's much due to having some helper routines such as floader, and MyRst etc. I can post some additional bits and code, but more important here is the general ideas here.
The markup in the popup div for uploading is this:
<div id="uploadfiles" runat="server" style="display:none">
<h3>Upload pictures for Hotel</h3>
<ajaxToolkit:AjaxFileUpload ID="AjaxFileUpload1" runat="server" Width="400px"
OnUploadComplete="AjaxFileUpload1_UploadComplete"
OnClientUploadCompleteAll="alldone"
/>
<asp:Button ID="cmdAllDone" runat="server" Text="All done"
ClientIDMode="Static"
OnClick="cmdAllDone_Click" style="display:none"
/>
</div>
And to display the pictures? I had this markup:
<div style="float:left;margin-left:30px;margin-top:-60px">
<asp:Repeater ID="Repeater1" runat="server">
<ItemTemplate>
<asp:Image ID="Image1" runat="server"
width="356px"
ImageUrl='<%# "~/Content/Hotels/" + Eval("FileName") %>'
CssClass="myshadow"
/>
<br />
<br />
</ItemTemplate>
</asp:Repeater>
</div>
So, I used a repeater to display 1 or many images.
The Load pictures code is this:
void LoadPictures(int PKID)
{
string strSQL =
"SELECT * FROM tblHotelPictures WHERE Hotel_ID = @ID";
SqlCommand cmdSQL = new SqlCommand(strSQL);
cmdSQL.Parameters.Add("@ID", SqlDbType.Int).Value = PKID;
DataTable rstPictures = General.MyRstP(cmdSQL);
Repeater1.DataSource = rstPictures;
Repeater1.DataBind();
}