Imports BaseClasses Imports BaseClasses.Data Imports BaseClasses.Utils Imports BaseClasses.Utils.StringUtils Namespace Persons.UI ' Typical customizations that may be done in this class include ' - adding custom event handlers ' - overriding base class methods ''' ''' The superclass (i.e. base class) for all Designer-generated record controls in this application. ''' ''' ''' ''' ''' Public Class BaseApplicationRecordControl Inherits System.Web.UI.Control ''' Allow for migration from earlier versions which did not have url encryption. Public Overridable Function ModifyRedirectUrl(ByVal redirectUrl As String, ByVal redirectArgument As String) As String Throw New Exception("This function should be implemented by inherited record control class.") End Function Public Overridable Function ModifyRedirectUrl(ByVal redirectUrl As String, ByVal redirectArgument As String, ByVal bEncrypt As Boolean) As String Throw New Exception("This function should be implemented by inherited record control class.") End Function Public Overridable Function EvaluateExpressions(ByVal redirectUrl As String, ByVal redirectArgument As String, ByVal bEncrypt As Boolean) As String Throw New Exception("This function should be implemented by inherited record control class.") End Function ''' Allow for migration from earlier versions which did not have url encryption. Public Overridable Function ModifyRedirectUrl(ByVal redirectUrl As String, ByVal redirectArgument As String, ByVal rec As IRecord) As String Return EvaluateExpressions(redirectUrl, redirectArgument, rec, False) End Function Public Overridable Function ModifyRedirectUrl(ByVal redirectUrl As String, ByVal redirectArgument As String, ByVal rec As IRecord, ByVal bEncrypt As Boolean) As String Return EvaluateExpressions(redirectUrl, redirectArgument, rec, bEncrypt) End Function Public Overridable Function EvaluateExpressions(ByVal redirectUrl As String, ByVal redirectArgument As String, ByVal rec As IRecord, ByVal bEncrypt As Boolean) As String Const PREFIX_NO_ENCODE As String = "NoUrlEncode:" Dim finalRedirectUrl As String = redirectUrl Dim finalRedirectArgument As String = redirectArgument If (finalRedirectUrl Is Nothing OrElse finalRedirectUrl.Trim = "") Then Return finalRedirectUrl ElseIf (finalRedirectUrl.IndexOf("{"c) < 0) Then Return finalRedirectUrl Else 'The old way was to pass separate URL and arguments and use String.Format to 'do the replacement. Example: ' URL: EditProductsRecord?Products={0} ' Argument: PK 'The new way to is pass the arguments directly in the URL. Example: ' URL: EditProductsRecord?Products={PK} 'If the old way is passsed, convert it to the new way. If (Len(finalRedirectArgument) > 0) Then Dim arguments() As String = Split(finalRedirectArgument, ",") Dim i As Integer For i = 0 To (arguments.Length - 1) finalRedirectUrl = finalRedirectUrl.Replace("{" & i.ToString & "}", "{" & arguments(i) & "}") Next finalRedirectArgument = "" End If 'Evaluate all of the expressions in the RedirectURL 'Expressions can be of the form [ControlName:][NoUrlEncode:]Key[:Value] Dim remainingUrl As String = finalRedirectUrl While (remainingUrl.IndexOf("{"c) >= 0) And (remainingUrl.IndexOf("}"c) > 0) And _ (remainingUrl.IndexOf("{"c) < remainingUrl.IndexOf("}"c)) Dim leftIndex As Integer = remainingUrl.IndexOf("{"c) Dim rightIndex As Integer = remainingUrl.IndexOf("}"c) Dim expression As String = remainingUrl.Substring(leftIndex + 1, rightIndex - leftIndex - 1) Dim origExpression As String = expression remainingUrl = remainingUrl.Substring(rightIndex + 1) Dim skip As Boolean = False Dim returnEmptyStringOnFail As Boolean = False Dim prefix As String = Nothing 'Check to see if this control must evaluate the expression If (expression.IndexOf(":") > 0) Then prefix = expression.Substring(0, expression.IndexOf(":")) End If If (Not IsNothing(prefix)) AndAlso (prefix.Length > 0) AndAlso _ (Not (InvariantLCase(prefix) = InvariantLCase(PREFIX_NO_ENCODE))) AndAlso _ (Not BaseRecord.IsKnownExpressionPrefix(prefix)) Then 'Remove the ASCX Prefix Dim IdString As String = Me.ID If IdString.StartsWith("_") Then IdString = IdString.Remove(0, 1) End If 'The prefix is a control name. If (prefix = IdString) Then 'This control is responsible for evaluating the expression, 'so if it can't be evaluated then return an empty string. returnEmptyStringOnFail = True expression = expression.Substring(expression.IndexOf(":") + 1) Else 'It's not for this control to evaluate so skip. skip = True End If End If If (Not skip) Then Dim bUrlEncode As Boolean = True If (InvariantLCase(expression).StartsWith(InvariantLCase(PREFIX_NO_ENCODE))) Then bUrlEncode = False expression = expression.Substring(PREFIX_NO_ENCODE.Length) End If Dim result As Object = Nothing Try If (Not IsNothing(rec)) Then result = rec.EvaluateExpression(expression) End If Catch ex As Exception 'Fall through End Try If (Not IsNothing(result)) Then result = result.ToString() End If If (IsNothing(result)) Then If (Not returnEmptyStringOnFail) Then Return finalRedirectUrl Else result = String.Empty End If End If If (bUrlEncode) Then result = System.Web.HttpUtility.UrlEncode(DirectCast(result, String)) If (IsNothing(result)) Then result = String.Empty End If End If If (bEncrypt) Then If Not (IsNothing(result)) Then result = DirectCast(Me.Page, BaseApplicationPage).Encrypt(DirectCast(result, String)) End If End If finalRedirectUrl = finalRedirectUrl.Replace("{" & origExpression & "}", DirectCast(result, String)) End If End While End If 'If there are still expressions to evaluate. Forward to the page for further processing. Return finalRedirectUrl End Function ''' ''' Get the Id of the parent table control. We navigate up the chain of ''' controls until we find the table control. Note that the first table ''' control above the record control would be the parent. You cannot have ''' a record control embedded in a different parent control other than its parent. ''' ''' The Id of the parent table control. Public Overridable Function GetParentTableControlID() As String Dim parent As BaseApplicationTableControl = Me.GetParentTableControl() If Not (IsNothing(parent)) Then Return parent.ID Return "" End Function #Region " Methods to manage saving and retrieving control values to session. " Protected Sub Control_SaveControls_Unload(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Unload If DirectCast(Me.Page, BaseApplicationPage).ShouldSaveControlsToSession Then Me.SaveControlsToSession() End If End Sub Protected Overridable Sub SaveControlsToSession() End Sub Protected Sub Control_ClearControls_PreRender(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.PreRender Me.ClearControlsFromSession() End Sub Protected Overridable Sub ClearControlsFromSession() End Sub Public Sub SaveToSession( _ ByVal control As Control, _ ByVal value As String) SaveToSession(control.UniqueID, value) End Sub Public Function GetFromSession( _ ByVal control As Control, _ ByVal defaultValue As String) As String Return GetFromSession(control.UniqueID, defaultValue) End Function Public Function GetFromSession(ByVal control As Control) As String Return GetFromSession(control.UniqueID, Nothing) End Function Public Sub RemoveFromSession(ByVal control As Control) RemoveFromSession(control.UniqueID) End Sub Public Function InSession(ByVal control As Control) As Boolean Return InSession(control.UniqueID) End Function Public Sub SaveToSession( _ ByVal control As Control, _ ByVal variable As String, _ ByVal value As String) SaveToSession(control.UniqueID & variable, value) End Sub Public Function GetFromSession( _ ByVal control As Control, _ ByVal variable As String, _ ByVal defaultValue As String) As String Return GetFromSession(control.UniqueID & variable, defaultValue) End Function Public Sub RemoveFromSession( _ ByVal control As Control, _ ByVal variable As String) RemoveFromSession(control.UniqueID & variable) End Sub Public Function InSession( _ ByVal control As Control, _ ByVal variable As String) As Boolean Return InSession(control.UniqueID & variable) End Function Public Sub SaveToSession( _ ByVal name As String, _ ByVal value As String) Me.Page.Session()(GetValueKey(name)) = value End Sub Public Function GetFromSession( _ ByVal name As String, _ ByVal defaultValue As String) As String Dim value As String = CType(Me.Page.Session()(GetValueKey(name)), String) If value Is Nothing OrElse value.Trim() = "" Then value = defaultValue End If Return value End Function Public Function GetFromSession(ByVal name As String) As String Return GetFromSession(name, Nothing) End Function Public Sub RemoveFromSession(ByVal name As String) Me.Page.Session.Remove(GetValueKey(name)) End Sub Public Function InSession(ByVal name As String) As Boolean Return (Not Me.Page.Session(GetValueKey(name)) Is Nothing) End Function Public Function GetValueKey(ByVal name As String) As String Return Me.Page.Session.SessionID & Me.Page.AppRelativeVirtualPath & name End Function #End Region ''' ''' Get the parent table control. We navigate up the chain of ''' controls until we find the table control. Note that the first table ''' control above the record control would be the parent. You cannot have ''' a record control embedded in a different parent control other than its parent. ''' ''' The Id of the parent table control. Public Overridable Function GetParentTableControl() As BaseApplicationTableControl Try Dim parent As Control = Me.Parent While Not (IsNothing(parent)) If TypeOf parent Is BaseApplicationTableControl Then Return CType(parent, BaseApplicationTableControl) End If parent = parent.Parent End While Catch ex As Exception ' Ignore and return Nothing End Try Return Nothing End Function ''' ''' The row number of this record control within the table control. ''' This function is called as {TableName}TableControlRow.ROWNUM(). ''' To make sure all the formula functions are in the same location, we call ''' the ROWNUM function in the FormulaUtils class, which actually does the work ''' and return the value. The function in FormulaUtils will need to know the ''' TableControl, so it is passed as the first instance. ''' The row number is 1 based. ''' ''' The row number of this row relative to the other rows in the table control. Public Function RowNum() As Decimal Return FormulaUtils.RowNum(Me.GetParentTableControl(), Me) End Function ''' ''' The rank of this field relative to other fields in the table control. ''' This function is called as {TableName}TableControlRow.RANK(). ''' Say there are 5 rows and they contain 57, 32, 12, 19, 98. ''' Their respecitive ranks will be 4, 3, 1, 2, 5 ''' To make sure all the formula functions are in the same location, we call ''' the RANK function in the FormulaUtils class, which actually does the work ''' and return the value. The function in FormulaUtils will need to know the ''' TableControl, so it is passed as the first instance. ''' The rank is 1 based. ''' ''' The string name of the UI control (e.g., "UnitPrice") ''' The rank of this row relative to the other rows in the table control.. Public Function Rank(ByVal controlName As String) As Decimal Return FormulaUtils.Rank(Me.GetParentTableControl(), Me, controlName) End Function ''' ''' The running total of the field. ''' This function is called as {TableName}TableControlRow.RUNNINGTOTAL(). ''' Say there are 5 rows and they contain 57, 32, 12, 19, 98. ''' The respecitive values for running totals will be be 57, 89, 101, 120, 218 ''' To make sure all the formula functions are in the same location, we call ''' the RUNNINGTOTAL function in the FormulaUtils class, which actually does the work ''' and return the value. The function in FormulaUtils will need to know the ''' TableControl, so it is passed as the first instance. ''' ''' The string name of the UI control (e.g., "UnitPrice") ''' The running total of the row. Public Function RunningTotal(ByVal controlName As String) As Decimal Return FormulaUtils.RunningTotal(Me.GetParentTableControl(), Me, controlName) End Function ''' ''' Store the UI data within the current record or row control and return as hashtable ''' ''' ''' Public Overridable Function PreservedUIData() As Hashtable ' This method get the UI data within the current record and return them as Hastable Dim uiData As New Hashtable Dim controls() As Control = BaseClasses.Utils.MiscUtils.FindControlsRecursively(Me) For Each control As Control In controls If control.ID <> "" AndAlso Not uiData.ContainsKey(control.ID) Then If control.GetType() Is GetType(TextBox) Then Dim textbox As TextBox = DirectCast(control, TextBox) uiData.Add(textbox.ID, textbox.Text) ElseIf control.GetType() Is GetType(Literal) Then Dim literal As Literal = DirectCast(control, Literal) uiData.Add(literal.ID, literal.Text) ElseIf control.GetType() Is GetType(Label) Then Dim label As Label = DirectCast(control, Label) uiData.Add(label.ID, label.Text) ElseIf control.GetType() Is GetType(CheckBox) Then Dim checkbox As CheckBox = DirectCast(control, CheckBox) uiData.Add(checkbox.ID, checkbox.Checked) ElseIf control.GetType() Is GetType(Button) Then Dim button As Button = DirectCast(control, Button) uiData.Add(button.ID, button.Text) ElseIf control.GetType() Is GetType(LinkButton) Then Dim linkButton As LinkButton = DirectCast(control, LinkButton) uiData.Add(linkButton.ID, linkButton.Text) ElseIf control.GetType() Is GetType(ListBox) Then Dim listbox As ListBox = DirectCast(control, ListBox) uiData.Add(listbox.ID, GetValueSelectedPageRequest(listbox)) ElseIf control.GetType() Is GetType(DropDownList) Then Dim dropdownList As DropDownList = DirectCast(control, DropDownList) uiData.Add(dropdownList.ID, GetValueSelectedPageRequest(dropdownList)) ElseIf control.GetType() Is GetType(DropDownList) Then Dim radioButtonList As RadioButtonList = DirectCast(control, RadioButtonList) uiData.Add(radioButtonList.ID, GetValueSelectedPageRequest(radioButtonList)) ElseIf control.GetType().GetInterface("IDatePagination") IsNot Nothing OrElse _ control.GetType().GetInterface("IDatePaginationMobile") IsNot Nothing Then ' Save the pagination's Interval and FirstStartDate and restore it by these values later Dim props() As System.Reflection.PropertyInfo = control.GetType().GetProperties() Dim ht As New Hashtable For Each prop As System.Reflection.PropertyInfo In props Dim descriptor As System.ComponentModel.PropertyDescriptor = System.ComponentModel.TypeDescriptor.GetProperties(control.GetType())(prop.Name) If descriptor.Name = "Interval" Then ht.Add("Interval", prop.GetValue(control, Nothing).ToString()) ElseIf descriptor.Name = "FirstStartDate" Then ht.Add("FirstStartDate", prop.GetValue(control, Nothing).ToString()) End If Next uiData.Add(control.ID, ht) End If End If Next Return uiData End Function End Class End Namespace