Although the ModalPopulExtender isn’t new at all there are still countless poeple who search the web for a comprehensive sample on how a ModalPopupExtender is used from a GridView.
First of all you’ld need to have a Button in each row which should trigger the ModalPopupExtender, then you would need to have an instance of a ModalPopupExtender with the TargetControlID set to the ID of that Button.
On the page you should create a Panel which the one which should popup whenever you press the button inside the GridView. This is the preeliminary setup. Because you don’t just pop up a modal “Window” on your form for fun … you need controls to interact with the user! For example one which should Cancel the operation and the other one which should proceed the operation. These can be using the OkControlID and the CancelControlID of the ModalPopopExtender.
This again is all fine … buuuuut without any postback there is no fun … what would be the real reason to use such a scenario where you don’t “save” the user’s choice. There has to be some functionality which sends the form back for processing.
Things that you need to consider in a sitation like this:
- The Cancel control simply hides the form (maybe you would need to clear the form before you let it pop up again!). Mind you, there is another way to do this using Javascript by setting the OnCancelScript property of the ModalPopupExtender.
- The OK control simply hides the form, which is not very good if you want to validate a field for example (and you still need to have the Modal Panel open if it didn’t pass the validation). Once again this can be done using the OnOkScript property of the ModalPopupExtender, but as more people are confortable with server-side validation than with client-side validation I’'ll show a way to leave the modal popup open even after a postback.
- The Control that triggers the opening of the ModalPopupExtender often needs a postback aswell to set up the Controls in the Modal Panel. (Ex: To load the firstname, lastname for which you wish to update the birthday details).
This example exposes a solution to all of the above points! To exemplify this I came up with a little scenario, you have a list of products which you can add to your cart! The GridView contains a button for each product, and by pressing it a Modal Popup comes up where you can fill in the Quantity you wish to order! Of course the modal popup contains the add button which acts as the “OKControlID” and a cancel button which is the Cancel Control ID. The OKControlID isn’t explicitely set because it would automatically hide the ModalPopup, so the actuall showing and hiding is done on the codebehind.
<asp:GridView ID="gv" runat="server" AutoGenerateColumns="False" DataKeyNames="ProductID"
DataSourceID="EntityDataSource1">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:ImageButton ID="btnSelect" runat="server"
ImageUrl="~/Images/addtocart.gif"
ImageAlign="AbsMiddle" OnClick="btnSelect_Click" />
<ajax:ModalPopupExtender ID="gv_ModalPopupExtender" runat="server"
TargetControlID="btnSelect"
PopupControlID="pnlModalPanel"
CancelControlID="btnCancel"
BackgroundCssClass="modalBackground">
</ajax:ModalPopupExtender>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="ProductID" HeaderText="ID"
ReadOnly="True" SortExpression="ProductID" />
<asp:BoundField DataField="ProductName" HeaderText="ProductName"
SortExpression="ProductName" />
<asp:BoundField DataField="ProductPrice" HeaderText="ProductPrice"
SortExpression="ProductPrice" DataFormatString="{0:C}" />
</Columns>
</asp:GridView>
* Notice how each row in the GridView (except of course the header and the footer) contains an ImageButton and a ModalPopupExtender.
For a visually pleasing result the BackgroundCssClass of the ModalPopupExtender is set. You could use the following style for a start:
<style type="text/css">
.modalBackground
{
background-color: Black;
filter: alpha(opacity=80);
opacity: 0.8;
z-index: 10000;
}
</style>
The panel that will pop up can be inserted into an UpdatePanel so that when there is an async postback so people can’t notice the whole page bouncing back and forth. I’ve put the pnlModalPanel inside an UpdatePanel because the btnAddtoCart button needs to do some logic on the codebehind.
<asp:Panel ID="pnlModalPanel" runat="server" Style="display: none;">
<table>
<tr align="center">
<td colspan="2">
<asp:Label ID="lblQuantity" runat="server"
ForeColor="White">Quantity:</asp:Label>
<asp:TextBox ID="txtQuantity" runat="server"></asp:TextBox>
</td>
</tr>
<tr>
<td align="left">
<asp:Button ID="btnAddToCart" runat="server"
Text="Add to Cart" OnClick="btnAddToCart_Click" />
</td>
<td align="right">
<asp:Button ID="btnCancel" runat="server" Text="Cancel" />
</td>
</tr>
</table>
</asp:Panel>
The first noticeable thing that happens on codebehind is that I set the OnClientClick attribute of the btnAddToCart button, so that it will post back.
protected void Page_Load(object sender, EventArgs e)
{
btnAddToCart.OnClientClick = String.Format("functionPostback('{0}','{1}')",
btnAddToCart.UniqueID, "");
}
Because I manually want to show the modal popup (this might be due to the fact that the controls inside the popup have to initialized according to the pressed button or row). This is not available in my example but maybe it would be good to load the product name and price inside the modal popup so we can insert the correct quantity accoring to our budget. This is why I’m showing the modal popup from server side. In my example I’m only clearing the quantity textbox.
protected void btnSelect_Click(object sender, ImageClickEventArgs e)
{
GridViewRow row = ((GridViewRow)((ImageButton)sender).NamingContainer);
//NamingContainer return the container that the control sits in
AjaxControlToolkit.ModalPopupExtender mpe =
(AjaxControlToolkit.ModalPopupExtender)row.FindControl("mpe");
txtQuantity.Text = ""; //reset the quantity textbox
mpe.Show(); //show the modal popup extender
}
The next thing to do is to handle the logic of the btnAddtoCart button where for the sake of the example I’m only setting a label to the quantity that has been selected!
protected void btnAddToCart_Click(object sender, EventArgs e)
{
lblMessage.Text = txtQuantity.Text + " items have been added!";
txtQuantity.Text = ""; //reset the quantity textbox
}
A tricky situation for the btnAddToCart_Click function is when the user would like more products than what the you can deliver (not enough products in stock, etc). In that case you would need to set a label inside the ModalPanel to a message telling the customer that there is a certain problem. The important thing is that after the postback ends the ModalPopup needs to be shown again. You need to find the instance of the ModalPopupExtender that has been shown in the first place and then call the Show() method on it.
Working with the ModalPopupExtender in more complex situations can be quite tricky but the yielded result can be ever more satisfactory if you get it right.
If you need any assistance don’t hesitate to write me and together we could find a solution, and if you liked this post don’t forget to kick it!