Imports System.ComponentModel Imports DevExpress.XtraEditors Imports DevExpress.XtraEditors.Controls Imports DevExpress.XtraLayout Imports DevExpress.XtraTab Imports DigitalData.Modules.Language.Utils Imports DigitalData.Modules.Logging ''' ''' ''' Public Class ClassDetailPageManager Private ReadOnly LogConfig As LogConfig Private ReadOnly Logger As Logger Private ReadOnly HostForm As IAdminForm Public Items As New Dictionary(Of String, DetailPage) Public Event AnyControl_Focus As EventHandler(Of DetailPageEventArgs) Public Event AnyControl_Changed As EventHandler(Of DetailPageEventArgs) Public Event CurrentPage_Changed As EventHandler(Of DetailPageEventArgs) Private RaiseChangedEvents As Boolean = True Private CurrentPage As DetailPage Public Property Current As DetailPage Get Return CurrentPage End Get Set(value As DetailPage) CurrentPage = value RaiseEvent CurrentPage_Changed(Me, New DetailPageEventArgs With {.Page = CurrentPage}) End Set End Property Public Class DetailPageEventArgs Public Property Page As DetailPage End Class ''' ''' An object representing a section of a form to edit an entity, ex. a user ''' ''' A Page to edit would be called the user page. Public Class DetailPage ''' ''' Is this the primary entity to be edited in this form? ''' Public Property IsPrimary As Boolean = False ''' ''' Is this an insert of a new object? ''' ''' Public Property IsInsert As Boolean = False ''' ''' The tab page containing the page. This can be left empty ''' Public Property TabPage As XtraTabPage = Nothing ''' ''' The Name of the Page which the user will see ''' Public Property Name As String ''' ''' The Binding Source for the Page ''' Public Property BindingSource As BindingSource ''' ''' The Bound Datatable in the Dataset (eg. MyDataset.TB_FOO_TABLE) ''' Public Property DataTable As DataTable ''' ''' The TextEdit Control containing the AddedWho value ''' Public Property AddedWhoEdit As TextEdit ''' ''' The TextEdit Control containing the ChangedWhoEdit value ''' Public Property ChangedWhoEdit As TextEdit End Class ''' ''' Detail page which represents the primary page of a form ''' Public Class PrimaryPage Inherits DetailPage Public Sub New(Insert As Boolean) IsInsert = Insert IsPrimary = True End Sub End Class Public Class ComboBoxItem Public Property Text Public Property Value Public Overrides Function ToString() As String Return Text End Function End Class Public Sub New(LogConfig As LogConfig, Form As IAdminForm, LayoutControls As List(Of LayoutControl)) Me.LogConfig = LogConfig Logger = LogConfig.GetLogger() HostForm = Form For Each oLayoutControl In LayoutControls AddHandler oLayoutControl.Click, AddressOf Handle_Focus AddHandler oLayoutControl.GotFocus, AddressOf Handle_Focus For Each oContainer As BaseLayoutItem In oLayoutControl.Root.Items Dim oItem As LayoutControlItem If TypeOf oContainer IsNot LayoutControlItem Then Continue For End If oItem = oContainer If TypeOf oItem Is EmptySpaceItem Then Continue For End If If TypeOf oItem.Control IsNot BaseEdit Then Continue For End If Dim oControl As BaseEdit = oItem.Control AddHandler oControl.GotFocus, AddressOf Handle_Focus AddHandler oControl.EditValueChanged, AddressOf Handle_EditValueChanged AddHandler oControl.Validating, AddressOf Handle_Validating Next 'For Each oContainer As LayoutControlItem In oLayoutControl.Root.Items ' If TypeOf oContainer Is EmptySpaceItem Then ' Continue For ' End If ' If TypeOf oContainer.Control IsNot BaseEdit Then ' Continue For ' End If ' Dim oControl As BaseEdit = oContainer.Control ' AddHandler oControl.GotFocus, AddressOf Handle_Focus ' AddHandler oControl.EditValueChanged, AddressOf Handle_EditValueChanged ' AddHandler oControl.Validating, AddressOf Handle_Validating 'Next Next End Sub ''' ''' Add a new DetailPage or a new PrimaryPage ''' Public Sub Add(Page As DetailPage) If Page.TabPage Is Nothing Then Items.Add("Primary", Page) Else Items.Add(Page.TabPage.Name, Page) End If AddHandler Page.BindingSource.AddingNew, Sub(sender As Object, e As EventArgs) RaiseChangedEvents = False Page.AddedWhoEdit.EditValue = Environment.UserName RaiseChangedEvents = True End Sub End Sub ''' ''' Add a list of new DetailPages or new PrimaryPages ''' Public Sub AddRange(ParamArray Pages As DetailPage()) For Each oPage In Pages Add(oPage) Next End Sub ''' ''' Get the DetailPage which uses the given `TabPage` ''' Public Function GetDetailPage(TabPage As XtraTabPage) As DetailPage Try Dim oItem = Items. Where(Function(Item) TabPage.Equals(Item.Value.TabPage)). FirstOrDefault() Return oItem.Value Catch ex As Exception Return Nothing End Try End Function Public Function PrepareLoad() As Boolean Dim oItem = Items. Where(Function(Item) Item.Value.IsPrimary). FirstOrDefault() Dim oPage = oItem.Value If oPage Is Nothing Then Return False End If If oPage.IsInsert Then RaiseChangedEvents = False oPage.BindingSource.AddNew() RaiseChangedEvents = True End If CurrentPage = oPage Return True End Function ''' ''' Saves the pending changes to the binding source ''' ''' True, if changes were made, otherwise False Public Function PrepareSave() As Boolean Dim oPage = CurrentPage If oPage Is Nothing Then Return False End If Try oPage.BindingSource.EndEdit() If oPage.DataTable.GetChanges() IsNot Nothing Then RaiseChangedEvents = False HostForm.HasChanges = True If oPage.IsInsert Then oPage.AddedWhoEdit.EditValue = My.Application.User.UserName Else oPage.ChangedWhoEdit.EditValue = My.Application.User.UserName End If RaiseChangedEvents = True oPage.BindingSource.EndEdit() Return True Else Return False End If Catch ex As Exception Logger.Error(ex) Return False End Try End Function Private Sub Handle_Validating(sender As Object, e As BaseEditValidatingEventArgs) Dim oControl As BaseEdit = sender Dim oColumn As DataColumn = Get_DataColumnFromBaseEdit(oControl) If oColumn IsNot Nothing Then Dim oNullable As Boolean = oColumn.AllowDBNull If oNullable = False Then If TypeOf oControl Is ComboBoxEdit AndAlso DirectCast(oControl, ComboBoxEdit).SelectedIndex = -1 Then e.ErrorText = "Please select a value from the list." e.Cancel = True ElseIf NotNull(oControl.EditValue.ToString, String.Empty) = String.Empty Then e.ErrorText = "Please input a value" e.Cancel = True End If End If End If End Sub Private Function Get_DataColumnFromBaseEdit(Control As BaseEdit) As DataColumn Dim oBinding As Binding = Control.DataBindings.Item("EditValue") If Control.DataBindings.Count = 0 OrElse oBinding Is Nothing Then Return Nothing End If If oBinding.DataSource Is Nothing Then Return Nothing End If If TypeOf oBinding.DataSource IsNot BindingSource Then Return Nothing End If Try Dim oSource As BindingSource = oBinding.DataSource Dim oTableName As String = oSource.DataMember Dim oDataSet As DataSet = oSource.DataSource Dim oTable = oDataSet.Tables(oTableName) Dim oColumnName As String = oBinding.BindingMemberInfo.BindingField Dim oColumn As DataColumn = oTable.Columns.Item(oColumnName) Return oColumn Catch ex As Exception Logger.Error(ex) Return Nothing End Try End Function Private Sub Handle_Focus(sender As Control, e As EventArgs) Dim oControl As Control = sender Dim oLayoutControl As LayoutControl = Nothing ' Get the Layout Control containing the Edit Contol If TypeOf oControl.Parent Is LayoutControl Then oLayoutControl = oControl.Parent ElseIf TypeOf oControl Is LayoutControl Then oLayoutControl = oControl End If If oLayoutControl Is Nothing Then Exit Sub End If If TypeOf oLayoutControl.Parent Is XtraTabPage Then Dim oTabPage As XtraTabPage = oLayoutControl.Parent If Items.ContainsKey(oTabPage.Name) Then CurrentPage = Items.Item(oTabPage.Name) Dim oData As New DetailPageEventArgs With {.Page = Items.Item(oTabPage.Name)} RaiseEvent CurrentPage_Changed(Me, oData) RaiseEvent AnyControl_Focus(oControl, oData) Else CurrentPage = Nothing RaiseEvent CurrentPage_Changed(Me, Nothing) RaiseEvent AnyControl_Focus(oControl, Nothing) End If End If End Sub Private Sub Handle_EditValueChanged(sender As BaseEdit, e As EventArgs) Dim oControl As BaseEdit = sender If RaiseChangedEvents = False Then Exit Sub End If ' Get the Layout Control containing the Edit Contol If TypeOf oControl.Parent Is LayoutControl Then Dim oLayoutControl As LayoutControl = oControl.Parent ' Get the TabPage containing the Layout Control If TypeOf oLayoutControl.Parent Is XtraTabPage Then Dim oTabPage As XtraTabPage = oLayoutControl.Parent If Items.ContainsKey(oTabPage.Name) Then Dim oData As New DetailPageEventArgs With {.Page = Items.Item(oTabPage.Name)} RaiseEvent AnyControl_Changed(oControl, oData) Else RaiseEvent AnyControl_Changed(oControl, Nothing) End If End If End If End Sub End Class