I think you best consider having this pop up appear on the CURRENT page.
And now that you want to restrict to "one", then that makes this a WHOLE lot less work.
There are more "dialog" systems then flavors of ice cream to choose from.
but, the two most common are the bootstrap ones, and the one from jQuery.UI.
I find the jQuery.UI VERY easy to work with - and you can control position with much greater ease then bootstrap ones.
And given that you have a SUPER high chance of already having jQuery, then adopting jQuery.UI from the same folks makes all the more sense.
And jQuery.UI dialogs can be "modal", and that means focus can't get out of the dialog until you "ok" or "save" or whatever.
So, lets take a simple GridView. Say we have some rows, and a "image".
When we click on the edit button, we pop a dialog with the picture, and also allow you to edit the comments.
So, our Grid is say this:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" CssClass="table" >
<Columns>
<asp:BoundField DataField="Fighter" HeaderText="Fighter" />
<asp:BoundField DataField="Engine" HeaderText="Engine" />
<asp:BoundField DataField="Thrust" HeaderText="Thrust" />
<asp:BoundField DataField="Description" HeaderText="Description" />
<asp:TemplateField HeaderText="View">
<ItemTemplate>
<asp:ImageButton ID="cmdView" runat="server" Width="150px"
ImageUrl = '<%# Eval("ImagePath") %>'
OnClick="cmdView_Click" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Code on page load is thus this:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadGrid();
}
void LoadGrid()
{
SqlCommand cmdSQL = new SqlCommand("SELECT * FROM Fighters");
GridView1.DataSource = MyRstP(cmdSQL);
GridView1.DataBind();
}
And now we have this:

So, the way jQuery.UI works?
You create a simple "div" on the same page, and it will become your "dialog"
You then hide with style=display:none.
So our markup for this "div" to disaplay the picture "big" and edit comments is this
(we drop it below the GV)
So, we have this simple markup to display picture, and let user edit comments for the picture:
<div id="EditOne" runat="server" style="text-align:center;display:none" clientidmode="static">
<br />
<asp:Image ID="Image1" runat="server" width="90%" />
<br />
<h4>Edit Description</h4>
<asp:TextBox ID="txtDescription" runat="server"
TextMode="MultiLine" Columns="90" Height="100px">
</asp:TextBox>
<br />
</div>
<asp:Button ID="cmdSave" runat="server" Text="Save" ClientIDMode="Static"
style="display:none" OnClick="cmdSave_Click"/>
Note careful in above - right below the div, I have a hidden save button.
So, now the jQuery routine that we pop to display this div as a dialog:
this:
<script>
function popimage(btn) {
pWidth = "50%"
myDialog = $("#EditOne");
myDialog.dialog({
title: "Edit Comments",
modal: true,
width: pWidth,
closeText: "",
show: "fade",
buttons: {
Save: function () {
myDialog.dialog("close")
$('#cmdSave').click()
},
Cancel: function () {
myDialog.dialog("close")
}
}
})
}
</script>
So, now we only need our button row click from the grid (I used image button).
That code is this:
We get the current row PK id, pull from database, and fill out the "div", and then pop it:
protected void cmdView_Click(object sender, ImageClickEventArgs e)
{
ImageButton btn = (ImageButton)sender;
GridViewRow gRow = (GridViewRow)btn.NamingContainer;
int PK = (int)GridView1.DataKeys[gRow.RowIndex]["ID"];
SqlCommand cmdSQL =
new SqlCommand("SELECT * FROM Fighters WHERE ID = @ID");
cmdSQL.Parameters.Add("@ID", SqlDbType.Int).Value = PK;
DataTable rstFighter = MyRstP(cmdSQL);
Image1.ImageUrl = rstFighter.Rows[0]["ImagePath"].ToString();
txtDescription.Text = rstFighter.Rows[0]["Description"].ToString();
ViewState["rstFighter"] = rstFighter;
Page.ClientScript.RegisterStartupScript(
this.GetType(),"MyEdit","popimage()", true);
}
And now our save button, to send information back to database is this:
protected void cmdSave_Click(object sender, EventArgs e)
{
// Save comments (and other fields back to database)
DataTable rstFigher = (DataTable)ViewState["rstFighter"];
rstFigher.Rows[0]["Description"] = txtDescription.Text;
SaveData(rstFigher, "Fighters");
LoadGrid(); // refresh grid to show any edits
}
So, the results now look like this when I click on a row image:

Note how the web page behind goes "darker gray" and the pop up is model.
So, I would consider jQuery.UI dialogs.
And I did use two helper routines (after all, we don't write the same code over and over to get get a simple data table, right???).
Those two helper routines were:
DataTable MyRstP(SqlCommand cmdSQL)
{
DataTable rstData = new DataTable();
using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
{
using (cmdSQL)
{
cmdSQL.Connection = conn;
conn.Open();
rstData.Load(cmdSQL.ExecuteReader());
}
}
return rstData;
}
void SaveData(DataTable rstData,string sTable)
{
using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
{
using (SqlCommand cmdSQL = new SqlCommand("SELECT * FROM " + sTable, conn))
{
conn.Open();
SqlDataAdapter da = new SqlDataAdapter(cmdSQL);
SqlCommandBuilder daU = new SqlCommandBuilder(da);
da.Update(rstData);
}
}
}
So, as above shows you have complete control over closing the pop up dialogue, but MUCH more important we can then also with ease update the current page to reflect those changes ( in our example update the description text in our pick list GridView). And with both the grid display and editing on the same page we also require much less code.