My solution with Bootstrap modal window and Classic ASP.NET.
In bootstrap front-end framework there are many interracial element, that has different way and some difficulties to realization in classic ASP.NET, especially bootstrap modal.
At common, there are two different way to realize bootstrap modal window in classic ASP.NET - with ASP.NET postback and without postback. My solution to described below working with postback.
First of all, please let's see in to screen - how it look in the screen.
And how is possible to realize this solution in classic ASP.NET?
- 1. External user's interface.
- 2. Code of control with Delete button.
- 3. External hugging control and ASP.NET Form
- 4. Alert control.
- 5. FindControlRecursively extension function - my common ASP.NET expanding.
1. External user's interface.
In screen below you may see common scheme - to press button raises event PrepareDeleteOrder_Click, and when you decide to delete order, will be processing event DeleteOrder_Click.
This is external user's interface to my solution, but what exists inside in this solution? But to move farther we need to understand more about external interface of my solution. Let's look below.
First of all in ASP.NET before environment raise any event in body of program, will be working Form_load or another events, this my working in Form_prepender events because this is not a ASP.NET page (aspx), this is only a control (ASCX), and I want to prepare it to traveling to browser after main page is had prepared and full ready with data. So, my my Form_prepender looks like this:
This is main point of inside part of my solution, but we will speaking about it little bit later, because firstly we need to understand common postback structure of this solution, because this is ASP.NET.
...
1: Imports Extension3
2: Partial Class ProceedToCheckoutItem
3: Inherits CheckBasketCommon2
...
22: Dim AlertInterface1 As AlertInterface = Me.Page.FindControlRecursively("Alert1")
In preparation form to processing event, you may see two branch - when my form is only preparing to first traveling to browser. You may see, in this case modal window is hide.
...
24: AlertInterface1.Visible = False
...
Second part is more interesting, when postback will be arrived from modal window or from DeleteButton. Modal window will be open and show when alert control (with interface "AlertInterface1") stored special variables "AlertActionRequest".
...
29: 'if false, this is postback from another button
30: Dim AlertActionRequest As Boolean = AlertInterface1.AlertActionRequest
31: If AlertActionRequest Then
32:
33: If AlertInterface1.TypeOfAlert = AlertPopupType.AlertType.DeleteOrder Then
34: DeleteOrder_Click(DeleteOrder, Nothing)
35: ElseIf AlertInterface1.TypeOfAlert = AlertPopupType.AlertType.SaveToLater Or AlertInterface1.TypeOfAlert = AlertPopupType.AlertType.RestoreSaved Then
36: SaveItforLaterButton_Click(SaveItforLaterButton, Nothing)
37: End If
38:
39: AlertInterface1.Visible = False
...
If user press "Delete Order", raises event PrepareDeleteOrder_Click that give access to Alert control (with AlertInterface1) and make two point setting in this control request "AlertPopupType.AlertType.DeleteOrder" and stored another information about order to deleting. In this case, if you has good understanding ASP.NET, this variable "AlertPopupType.AlertType.DeleteOrder" is a my own implementation of common ASP.NET postback variable __EVENTTARGET.
...
757: Protected Sub PrepareDeleteOrder_Click(sender As Object, e As EventArgs) Handles DeleteOrder.Click
758: Dim AlertInterface1 As AlertInterface = Me.Page.FindControlRecursively("Alert1")
759: AlertInterface1.TypeOfAlert = AlertPopupType.AlertType.DeleteOrder
760: Dim ClientName As String = CurrentBasketItem.Rows(ItemIndex)("FirstName").ToString & " " & CurrentBasketItem.Rows(ItemIndex)("LastName").ToString
761: AlertInterface1.SetOrderInfo("Are you sure, you want to delete " & ClientName & "'s order?", ClientName)
762: AlertInterface1.Visible = True
763: AlertInterface1.txtTitle = CurrentBasketItem.Rows(ItemIndex)("Title")
764: AlertInterface1.txtFirstname = CurrentBasketItem.Rows(ItemIndex)("Firstname")
765: AlertInterface1.txtLastName = CurrentBasketItem.Rows(ItemIndex)("LastName")
...
775: End Sub
...
If postback is arrive from browser with setting "AlertPopupType.AlertType.DeleteOrder" (and in background with other data) this is marker than this postback is arrive from popup window. And ProceedToCheckoutItem_PreRender sub is executing sub DeleteOrder_Click.
...
777: Protected Sub DeleteOrder_Click(sender As Object, e As EventArgs)
...
786: Dim AlertInterface1 As AlertInterface = Me.Page.FindControlRecursively("Alert1")
787: Basket.DeleteOrderFromBasket(Trim(RetailerID), _
788: AlertInterface1.txtTitle, _
789: AlertInterface1.txtFirstname, _
790: AlertInterface1.txtLastName, _
...
821: End Sub
...
If you have understanding common postbeck structure and external interface of this solution - let's going farther, to internal structure of solution.
2. Code of control with Delete button.
This is big code with many thousands line of code and in description of this it does not matter.
Main reason of this big hierarchy to move functions of control from external part of ASP.NET solution (what contains page part of ASP.NET application) to part of ASP.NET application in folder APP_CODE, where all functions is be available for all ASP.NET application.
3. External hugging control and ASP.NET Form
This form contains control that has repiter and this control is include in ASP.NET Form. At common, this is big code too. But most important part of this code is not a big.
This ASP.NET form contains two controls. And one of thw most important part of this solution - the script to hide Bootstrap modal window.
1: <%@ Page Title=" Language="VB" MasterPageFile="~/BasketInterface.master" AutoEventWireup="false" CodeFile="ProceedToCheckout.aspx.vb" Inherits="ProceedToCheckout" %>
2: <%@ Register Src="~/CheckBasket.ascx" TagPrefix="uc1" TagName="CheckBasket" %>
3: <%@ Register Src="~/Alert.ascx" TagPrefix="uc1" TagName="Alert" %>
...
49: <asp:ScriptManager ID="script1" runat="server"></asp:ScriptManager>
50: <uc1:CheckBasket runat="server" ID="CheckBasket1" />
...
53: <uc1:Alert runat="server" ID="Alert1" />
54: <script type="text/javascript" >
55: $("#ModalAlert").on("hidden.bs.modal", function () {
56: });
57: </script>
...
And this is main part of hugging control, that include control with delete button.
1: <%@ Control Language="VB" AutoEventWireup="false" CodeFile="CheckBasket.ascx.vb" Inherits="CheckBasket" %>
2: <%@ Register src="ProceedToCheckoutItem.ascx" tagname="ProceedToCheckoutItem" tagprefix="uc1" %>
...
60: <asp:DataList runat="server" ID="proceed_checkout" RepeatDirection="Vertical" RepeatLayout="Table" OnItemDataBound="proceed_checkout_ItemDataBound" style="width:100%">
61: <ItemTemplate>
62: <uc1:ProceedToCheckoutItem ID="ProceedToCheckoutItem1" runat="server" />
63: </ItemTemplate>
64: </asp:DataList>
...
4. Alert control.
Popup window (in my solution named Alert1) has three parts. First of it is ASP.NET markup.
Main part of this code is javascript code and two button. I search a way to create gray background over modal window but not found it.
1: <%@ Control Language="VB" AutoEventWireup="false" CodeFile="Alert.ascx.vb" Inherits="Alert" %>
2:
3: <div id="ModalAlert" class="modal fade main-modal in" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" style="display: block; padding-right: 17px;">
4: <div class="modal-dialog" role="document">
5: <div class="modal-content" style="width: 600px;">
6: <div class="modal-header">
7: <asp:LinkButton id="CloseModal" runat="server" CssClass="close" data-dismiss="modal" aria-label="Close" >
8: <span aria-hidden="true">× </span>
9: </asp:LinkButton>
10: </div>
11: <div class="modal-body" style="margin-left: 30px;">
12: <asp:Label ID="MessageBody" runat="server" Font-Bold="True"></asp:Label><br />
13: </div>
14: <div class="modal-footer">
15: <asp:Button ID="DeleteOrder" style="margin-left: 50px;" CssClass="btn btn-white btns-groups pull-left" runat="server" Text="Yes, delete order" />
16: <asp:Button ID="NoDeleteOrder" CssClass="btn btn-white btns-groups pull-right" runat="server" Text="No, continue shoping" />
17: </div>
18: </div>
19: </div>
20: </div>
21:
22:
23:
24: <script type="text/javascript">
25: //problem - backdrop not working, but in browser console is work
26: //http://getbootstrap.com/customize/#modals
27: //https://www.w3schools.com/bootstrap/bootstrap_modal.asp
28: $("#ModalAlert").modal();
29: $("#ModalAlert").modal({ backdrop: true });
30: </script>
Second part of Popup window id code behind part. Its very simple:
1:
2: Partial Class Alert
3: Inherits AlertInterface
4:
5: Private Sub Alert_Load(sender As Object, e As EventArgs) Handles Me.PreRender
6: If Not IsPostBack Then
7: Me.AlertActionRequest = False
8: End If
9: If TypeOfAlert = AlertPopupType.AlertType.SaveToLater Then
10: 'msg1.Text = "You wand save order to later"
11: DeleteOrder.Text = "Yes, save to later"
12: ElseIf TypeOfAlert = AlertPopupType.AlertType.DeleteOrder Then
13: 'msg1.Text = "You wand to delete order"
14: DeleteOrder.Text = "Yes, delete order"
15: ElseIf TypeOfAlert = AlertPopupType.AlertType.RestoreSaved Then
16: 'msg1.Text = "You wand to restore order to basket"
17: DeleteOrder.Text = "Yes, restore order"
18: End If
19: End Sub
20: Protected Sub DeleteOrder_Click(sender As Object, e As EventArgs) Handles DeleteOrder.Click
21: Me.InvokeEvent(Me.ClientName)
22: Me.AlertActionRequest = True
23: Me.Visible = False
24: End Sub
25: Protected Sub CloseModal_Click(sender As Object, e As EventArgs) Handles CloseModal.Click
26: Me.Visible = False
27: End Sub
28: Protected Sub NoDeleteOrder_Click(sender As Object, e As EventArgs) Handles NoDeleteOrder.Click
29: Me.AlertActionRequest = False
30: Me.Visible = False
31: End Sub
32: End Class
Both of part above is placed in part with page and its interface is inaccessible in all application, especially in ProceedToCheckoutItem control and another contror. Therefore most important part of this control has moved in App_code.
Most interesting part of this code you may see below.
1: Imports Microsoft.VisualBasic
2:
3: Public Class AlertInterface
4: Inherits System.Web.UI.UserControl
5:
6: Public Event DeleteOrderClick(ClientName As String)
7:
8: Public Sub SetOrderInfo(MessageBody As String, ClientName As String)
9: Dim MessageBodyLabel As Label = Me.FindControl("MessageBody")
10: MessageBodyLabel.Text = MessageBody
11: Me.ClientName = ClientName
12: End Sub
13:
...
33: Public Property AlertActionRequest As Boolean
34: Get
35: Return ViewState("AlertActionRequest")
36: End Get
37: Set(value As Boolean)
38: ViewState("AlertActionRequest") = value
39: End Set
40: End Property
41:
42: Public Sub InvokeEvent(ClientName As String)
43: RaiseEvent DeleteOrderClick(ClientName)
44: End Sub
45:
46: Public Property TypeOfAlert As AlertPopupType.AlertType
47: Get
48: Return ViewState("TypeOfAlert")
49: End Get
50: Set(value As AlertPopupType.AlertType)
51: ViewState("TypeOfAlert") = value
52: End Set
53: End Property
54:
...
63:
64: Public Property txtFirstname As String
65: Get
66: Return ViewState("txtFirstname")
67: End Get
68: Set(value As String)
69: ViewState("txtFirstname") = value
70: End Set
71: End Property
72:
73: Public Property txtLastName As String
74: Get
75: Return ViewState("txtLastName")
76: End Get
77: Set(value As String)
78: ViewState("txtLastName") = value
79: End Set
80: End Property
...
145: End Class
What important in this code? First of all, event defined in this control is not working in ASP.NET. That need to understand any ASP.NET programmer, it is a correct syntax, but incorrect approach to move up information to high level from control. Correct solution is stored information (like AlertActionRequest) to Viewstate and check it in postback.
And second big important point that line 9 working! So, simple "findcontrol" in app_code may found anything ounside in APP_CODE part of application, in part with web forms. This is exception of common ASP.NET rules that means "only app_code part is accessible to any part of application, page part of all application will be create in runtime and not be accessible from code part". But in the same control page part is accebly by simple findcontrol function.
5. FindControlRecursively extension function - my common ASP.NET expanding.
But most interesting and difficult in ASP.NET (at common, and in this is most important part of my solution) - how to find Alert control in web form ProceedToCheckout.aspx?
Set of function from microsoft has only simple findcontrol function that working only in one level of included control. Therefore I expand standard set of ASP.NET function with my own function - FindControlRecursively, that check all level of control and can fount control Alert1 in ProceedToCheckout.aspx page.
This extension function is very important part of solution.
1: Imports Microsoft.VisualBasic
2:
3: Public Module Extension0
4:
5: <Runtime.CompilerServices.Extension()> _
6: Public Function FindControlRecursively(ByVal parentControl As Control, ByVal controlId As String) As Control
7:
8: If String.IsNullOrEmpty(controlId) = True OrElse controlId = String.Empty Then
9: Return Nothing
10: End If
11:
12: If parentControl.ID = controlId Then
13: Return parentControl
14: End If
15:
16: If parentControl.HasControls Then
17: For Each c As Control In parentControl.Controls
18: Dim child As Control = FindControlRecursively(c, controlId)
19: If child IsNot Nothing Then
20: Return child
21: End If
22: Next
23: End If
24:
25: Return Nothing
26:
27: End Function
28: End Module
Happy programing in VB and Classic ASP.NET !