How To: Using SF BO/Business Binding Source with DevExpress Scheduler/Calendar Control


Author
Message
Jeff Pagley
Jeff Pagley
StrataFrame User (465 reputation)StrataFrame User (465 reputation)StrataFrame User (465 reputation)StrataFrame User (465 reputation)StrataFrame User (465 reputation)StrataFrame User (465 reputation)StrataFrame User (465 reputation)StrataFrame User (465 reputation)StrataFrame User (465 reputation)
Group: StrataFrame Users
Posts: 223, Visits: 893
Is anyone using SF BO/Business Binding Source with DevExpress Scheduler/Calendar control?  I have successfully used it with the standard .NET table adapter/dataset.  I am not able to get it to work with the SF BO/BBS.  

I have looked at the SF Custom Business Binding Source example in Strataflix.   The Stratafix example is showing it used with reports.  Can anyone tell me if this SF custom BBS will work with the DevX scheduler/calendar control?  If so, do you have an example on how you did it or any tips/tricks on getting it to work right?

Thanks,

Jeff

Peter Jones
Peter Jones
Advanced StrataFrame User (504 reputation)Advanced StrataFrame User (504 reputation)Advanced StrataFrame User (504 reputation)Advanced StrataFrame User (504 reputation)Advanced StrataFrame User (504 reputation)Advanced StrataFrame User (504 reputation)Advanced StrataFrame User (504 reputation)Advanced StrataFrame User (504 reputation)Advanced StrataFrame User (504 reputation)
Group: Forum Members
Posts: 386, Visits: 2.1K
Hi Jeff,



We have used a BBS as the Appointments data source in a Scheduler Control. That part worked fine but I seem to remember we had a deal of problems just coming to grips with the concepts involved and, as I remember, either the DX documentation wasn't real good or I wasn't real smart in undertstanding it.



We did get it all working and it works well for us - just simple system housekeeping that we could have probably achieved easier by using the Windows Task Scheduler but we wanted more flexibilty and extensibility for the future.



FWIW following is all the code in form that contains the Scheduler Control. There may be bits in it that are useful to you but I certainly wouldn't say what we have done is 'best practice'. I know we made heavy going of it at times.



Cheers, Peter



Option Explicit On

Option Strict On



Imports System.Data.SqlClient

Imports DevExpress.XtraGrid

Imports DevExpress.XtraPrinting

Imports clsFU = UtilForms.clsFormUtility

Imports clsFP = UtilForms.clsFormPrint

Imports clsHE = UtilHelp.clsHelp

Imports clsLOC = UtilLocalisation.clsLocalise

Imports clsRTE = UtilRunTimeEnvironment.clsRunTimeEnv

Imports clsSSV = UtilSundry.clsServices

Imports clsLOG = UtilLogging.clsLogging



Imports MicroFour.StrataFrame.Messaging

Imports Microsoft.VisualBasic

Imports System

Imports System.Collections.Generic

Imports System.ComponentModel

Imports System.Data

Imports System.Drawing

Imports System.Text

Imports System.Windows.Forms

Imports DevExpress.XtraScheduler.UI

Imports DevExpress.XtraScheduler

Imports DevExpress.XtraScheduler.Native



'



Public Class frmSCH



#Region " Initialisation during form loading "

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load



' TMS Standard form configuration

clsFU.LocaliseAllControls(Me)

clsFU.ConfigureEmbeddedNavigator(Me, Me.Images16x16)

clsFU.SetLookAndFeel(Me.DefaultLookAndFeel1)

clsFU.SetTheFormTechName(Me)

clsFU.SetSundryProperties(Me, Me.Images32x32, clsRTE.RightToLeft, clsRTE.StartXPosition, clsRTE.StartYPosition)

clsFU.LocaliseSFMessages(Me)

clsFU.SetGridNonStandardProperties(Me)

Me.GradientFormHeader1.DetailText = clsRTE.CMPTanneryName







AddHandler schedulerControl1.SelectedAppointments.CollectionChanged, AddressOf SelectedAppointments_CollectionChanged

AddHandler schedulerControl1.SelectedAppointments.CollectionChanging, AddressOf SelectedAppointments_CollectionChanging

' Handle the ParseString and ConvertToString events of the HumanReadableTimeSpanHelper.

AddHandler HumanReadableTimeSpanHelper.ParseString, AddressOf OnParse

AddHandler HumanReadableTimeSpanHelper.ConvertToString, AddressOf OnToString



schedulerControl1.OptionsCustomization.AllowAppointmentConflicts = AppointmentConflictsMode.Allowed

schedulerControl1.OptionsCustomization.AllowAppointmentCopy = UsedAppointmentType.None

schedulerControl1.OptionsCustomization.AllowAppointmentMultiSelect = False



schedulerControl1.OptionsView.FirstDayOfWeek = DevExpress.XtraScheduler.FirstDayOfWeek.Sunday

schedulerControl1.OptionsView.HideSelection = False

schedulerControl1.OptionsView.NavigationButtons.Visibility = NavigationButtonVisibility.Always

schedulerControl1.OptionsView.ShowOnlyResourceAppointments = False

schedulerControl1.OptionsView.ToolTipVisibility = ToolTipVisibility.Always



schedulerControl1.OptionsBehavior.RecurrentAppointmentDeleteAction = RecurrentAppointmentAction.Series

schedulerControl1.OptionsBehavior.RecurrentAppointmentEditAction = RecurrentAppointmentAction.Series

schedulerControl1.OptionsBehavior.RemindersFormDefaultAction = RemindersFormDefaultAction.SnoozeAll

schedulerControl1.OptionsBehavior.SelectOnRightClick = True

schedulerControl1.OptionsBehavior.ShowRemindersForm = True



schedulerControl1.GroupType = SchedulerGroupType.Date



' Get the current schedule details from the database and populate the schedule

' with a data table.

CType(Me.PrimaryBusinessObject, UtilBOBase.boTMSMaintBase).TMSStandardFill()

SchedulerStorage1.Resources.DataSource = Nothing

SchedulerStorage1.Appointments.DataSource = Nothing

schedulerControl1.BeginUpdate()

SchedulerStorage1.BeginUpdate()

SchedulerStorage1.Appointments.DataSource = Me.BoSCH1.CurrentDataTable

SchedulerStorage1.EndUpdate()

schedulerControl1.EndUpdate()



End Sub

#End Region







#Region " DevExpress customised recurrence form handling "



Public Class MyAppointmentForm

Inherits AppointmentForm

Public Sub New(ByVal control As SchedulerControl, ByVal apt As Appointment)

MyBase.New(control, apt)

End Sub

Public Sub New(ByVal control As SchedulerControl, ByVal apt As Appointment, ByVal openRecurrenceForm As Boolean)

MyBase.New(control, apt, openRecurrenceForm)

End Sub

Protected Overrides Function CreateAppointmentRecurrenceForm(ByVal patternCopy As Appointment, ByVal firstDayOfWeek As DevExpress.XtraScheduler.FirstDayOfWeek) As Form

Dim frm As TMSSystemTableMaint.WindowsApplication1.XtraForm1 = New TMSSystemTableMaint.WindowsApplication1.XtraForm1(patternCopy, firstDayOfWeek, Me.Controller)



frm.LookAndFeel.ParentLookAndFeel = Me.LookAndFeel

frm.ShowExceptionsRemoveMsgBox = Me.Controller.AreExceptionsPresent()

Return frm



End Function



End Class





Private Sub schedulerControl1_EditAppointmentFormShowing(ByVal sender As Object, ByVal e As AppointmentFormEventArgs) Handles schedulerControl1.EditAppointmentFormShowing



Dim frm As New MyAppointmentForm(TryCast(sender, SchedulerControl), e.Appointment, e.OpenRecurrenceForm)



' Standard setting for TMS. Always recurring, always has a reminder and can only

' maintain in the recurrence form



' This works fine when the form is opened but when returning to the form

' from the recurring form all our Enabled = False are set back to True.



CType(frm.Controls("chkReminder"), DevExpress.XtraEditors.CheckEdit).EditValue = True

CType(frm.Controls("chkAllDay"), DevExpress.XtraEditors.CheckEdit).EditValue = False

CType(frm.Controls("cbReminder"), DevExpress.XtraScheduler.UI.DurationEdit).EditValue = Parse("0")



frm.Controls("edtStartTime").Enabled = False

frm.Controls("edtStartDate").Enabled = False

frm.Controls("edtEndTime").Enabled = False

frm.Controls("edtEndDate").Enabled = False

frm.Controls("chkAllDay").Enabled = False

frm.Controls("chkReminder").Enabled = False

frm.Controls("cbReminder").Enabled = False



If Me.BoSCH1.IsDirty Then

' Save the dataset to the database if it has changed.

Me.BoSCH1.Save()

End If

'---------------------------------------------



e.DialogResult = frm.ShowDialog()

e.Handled = True

End Sub





#End Region



#Region " Time span parsing - standard DX code "



Private Function Parse(ByVal str As String) As TimeSpan



End Function

' Custom parsing of a string to a TimeSpan value.

Private Sub OnParse(ByVal sender As Object, ByVal e As TimeSpanStringConvertEventArgs)

Dim val As Double

Try

Dim number As String = e.StringValue.Substring(0, e.StringValue.IndexOf(" minutes"))

val = Convert.ToDouble(number)

Catch

val = 0

End Try



e.TimeSpanValue = TimeSpan.FromMinutes(val)

e.Handled = True

End Sub



' Custom conversion of a TimeSpan value to a string.

Private Sub OnToString(ByVal sender As Object, ByVal e As TimeSpanStringConvertEventArgs)

e.StringValue = "0 minutes" ' e.TimeSpanValue.TotalMinutes.ToString() + "0 minutes"

e.Handled = True

End Sub





#End Region





#Region " TMS code for handling custom fields and propergating changes to the database "



Private Sub SchedulerStorage1_AppointmentDeleting(ByVal sender As Object, ByVal e As DevExpress.XtraScheduler.PersistentObjectCancelEventArgs) Handles SchedulerStorage1.AppointmentDeleting



' Delete the in the dataset

Me.UpdateCustomFieldsInBO(Me.BoSCH1.CurrentRowIndex, False, True)

InitCustomFieldsB4NewAndAfterDelete()



End Sub



Private Sub SchedulerStorage1_AppointmentInserting(ByVal sender As Object, ByVal e As DevExpress.XtraScheduler.PersistentObjectCancelEventArgs) Handles SchedulerStorage1.AppointmentInserting



Me.schedulerControl1.Visible = False

Me.btnSaveTMSInfoNewSchedule.Visible = True



InitCustomFieldsB4NewAndAfterDelete()



End Sub



Private Sub InitCustomFieldsB4NewAndAfterDelete()



Me.luScheduleJobType.EditValue = 1

Me.luScheduleRunOn.EditValue = 1

Me.txtSCHDXSubject.Text = ""

Me.txtSCHJobFolder.Text = ""

Me.txtSCHJobName.Text = ""

Me.txtSCHJobParameters.Text = ""

Me.txtSCHJobFolder.Focus()

Me.Refresh()

End Sub

Private Sub SchedulerStorage1_AppointmentInserted(ByVal sender As Object, ByVal e As DevExpress.XtraScheduler.PersistentObjectsEventArgs) Handles SchedulerStorage1.AppointmentsInserted



' Ensure the new Appointment has a valid GUID as its PK when it finally gets saved

' The new row is always at the end of the dataset.



' At this stage we haven't had a chance to enter our custom field values.

If BoSCH1.MoveLast Then

Me.UpdateCustomFieldsInBO(BoSCH1.CurrentRowIndex, True, False)

End If



End Sub



' Private Sub SelectedAppointments_CollectionChanged(ByVal sender As Object, ByVal e As DevExpress.XtraScheduler.CollectionChangedEventArgs(Of DevExpress.XtraScheduler.Appointment))



Private Sub SelectedAppointments_CollectionChanged(ByVal sender As Object, ByVal e As DevExpress.Utils.CollectionChangedEventArgs(Of Appointment))





' This code was used to show the custom field values on the main form.

' for the newly selected Appointment.



' Skip this if we are saving a new record

If Not Me.btnSaveTMSInfoNewSchedule.Visible Then



' Loop through all the selected appointments. Will only every be one becuause

' multi-select is turned off



For idx As Integer = 0 To schedulerControl1.SelectedAppointments.Count - 1



' This was needed because Custom Fields seem to 'disappear' at times. This

' may be my imagination



If Not schedulerControl1.SelectedAppointments(idx).CustomFields Is Nothing Then



' Set focus in the dataset to the appointment just selected.

If BoSCH1.SeekToPrimaryKey(schedulerControl1.SelectedAppointments(idx).CustomFields("SCHID")) Then



' Populate the custome text fields on the main form with the existing info from the dataset

If Not IsDBNull(Me.BoSCH1.SCHJobName) Then

Me.txtSCHJobName.Text = Me.BoSCH1.SCHJobName.ToString

End If



If Not IsDBNull(Me.BoSCH1.SCHJobParameters) Then

Me.txtSCHJobParameters.Text = Me.BoSCH1.SCHJobParameters.ToString

End If



If Not IsDBNull(Me.BoSCH1.SCHJobFolder) Then

Me.txtSCHJobFolder.Text = Me.BoSCH1.SCHJobFolder.ToString

End If



If Not IsDBNull(Me.BoSCH1.SCHDXSubject) Then

Me.txtSCHDXSubject.Text = Me.BoSCH1.SCHDXSubject.ToString

End If



If Not IsDBNull(Me.BoSCH1.SCHRunOn) Then

Me.luScheduleRunOn.EditValue = Me.BoSCH1.SCHRunOn

End If



If Not IsDBNull(Me.BoSCH1.SCHJobType) Then

Me.luScheduleJobType.EditValue = Me.BoSCH1.SCHJobType

End If



End If

End If

Next

End If

End Sub





' Private Sub SelectedAppointments_CollectionChanging(ByVal sender As Object, ByVal e As DevExpress.XtraScheduler.Native.CollectionChangingEventArgs(Of DevExpress.XtraScheduler.Appointment))



Private Sub SelectedAppointments_CollectionChanging(ByVal sender As Object, ByVal e As DevExpress.Utils.CollectionChangingEventArgs(Of Appointment))



' Loop through all the selected appointments. Will only every be one becuause

' multi-select is turned off. At this stage the selected Appointment is

' the one about to loose focus.



Dim UpdateNeeded As Boolean = False



For idx As Integer = 0 To schedulerControl1.SelectedAppointments.Count - 1



' This was needed because Custom Fields seem to disappear at times. This

' may be my imagination



If Not schedulerControl1.SelectedAppointments(idx).CustomFields Is Nothing Then



If BoSCH1.SeekToPrimaryKey(schedulerControl1.SelectedAppointments(idx).CustomFields("SCHID")) Then



' Only change the dataset if there has been a change to values

' in our custom fields.

If Me.BoSCH1.SCHJobName <> Me.txtSCHJobName.Text OrElse _

Me.BoSCH1.SCHJobParameters <> Me.txtSCHJobParameters.Text OrElse _

Me.BoSCH1.SCHJobFolder <> Me.txtSCHJobFolder.Text Then

UpdateNeeded = True

ElseIf Me.luScheduleRunOn.EditValue Is Nothing Then

UpdateNeeded = False

ElseIf Me.BoSCH1.SCHRunOn.Value <> CType(Me.luScheduleRunOn.EditValue, Integer) Then

UpdateNeeded = True

ElseIf Me.luScheduleJobType.EditValue Is Nothing Then

UpdateNeeded = False

ElseIf Me.BoSCH1.SCHJobType.Value <> CType(Me.luScheduleJobType.EditValue, Integer) Then

UpdateNeeded = True

End If



If UpdateNeeded Then

Me.UpdateCustomFieldsInBO(Me.BoSCH1.CurrentRowIndex, False, False)

End If

End If

End If

Next



End Sub





Private Sub btnSaveTMSInfo_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnSaveTMSInfoNewSchedule.Click



' Save the TMS specific info for a new record.

' New records are always at the end of the dataset.

If BoSCH1.MoveLast Then

Me.txtSCHDXSubject.Text = Me.BoSCH1.SCHDXSubject

Me.UpdateCustomFieldsInBO(Me.BoSCH1.CurrentRowIndex, False, False)

End If



' Back to normal maintenance

Me.txtSCHJobFolder.Focus()

Me.btnSaveTMSInfoNewSchedule.Visible = False

Me.schedulerControl1.Visible = True

Me.Refresh()



End Sub



Private Sub UpdateCustomFieldsInBO(ByVal RowIndex As Integer, ByVal CreatePKOnly As Boolean, ByVal DeleteOnly As Boolean)



' The MoveAbsolutes is needed because the code "boSCH1?? = txtSCH??" below actually

' sets the current row index in the BO to 0. No idea why.



' Updating the BO caused following events to fire. Cleary the appointements know

' when the underlying dataset changes. Anyway Removing and readding the handlers seemed

' fix that problem



RemoveHandler schedulerControl1.SelectedAppointments.CollectionChanging, AddressOf SelectedAppointments_CollectionChanging

RemoveHandler schedulerControl1.SelectedAppointments.CollectionChanged, AddressOf SelectedAppointments_CollectionChanged



If CreatePKOnly Then



Me.BoSCH1.MoveAbsolute(RowIndex)

Me.BoSCH1.SCHID = Guid.NewGuid



ElseIf DeleteOnly Then



Me.BoSCH1.MoveAbsolute(RowIndex)

Me.BoSCH1.DeleteCurrentRow()



Else

Me.BoSCH1.MoveAbsolute(RowIndex)

Me.BoSCH1.SCHJobFolder = Me.txtSCHJobFolder.Text



Me.BoSCH1.MoveAbsolute(RowIndex)

Me.BoSCH1.SCHJobName = Me.txtSCHJobName.Text



Me.BoSCH1.MoveAbsolute(RowIndex)

Me.BoSCH1.SCHJobParameters = Me.txtSCHJobParameters.Text



Me.BoSCH1.MoveAbsolute(RowIndex)

Me.BoSCH1.SCHJobType = CType(Me.luScheduleJobType.EditValue, Integer)



Me.BoSCH1.MoveAbsolute(RowIndex)

Me.BoSCH1.SCHRunOn = CType(Me.luScheduleRunOn.EditValue, Integer)



End If



Me.BoSCH1.MoveAbsolute(RowIndex)

Me.BoSCH1.Save()

Me.BoSCH1.MoveAbsolute(RowIndex)



AddHandler schedulerControl1.SelectedAppointments.CollectionChanging, AddressOf SelectedAppointments_CollectionChanging

AddHandler schedulerControl1.SelectedAppointments.CollectionChanged, AddressOf SelectedAppointments_CollectionChanged



End Sub

#End Region



#Region " Help button processing "



Private Sub btnHelp_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnHelp.Click



clsHE.FormHelpClicked(Me.Name, False, clsRTE.UserName)



End Sub



#End Region



#Region " Standard Event Handling for Form using clsFormUtility "



Private Sub LogInfo(ByVal Message As String)

Dim LogMsg As New System.Text.StringBuilder

LogMsg.AppendFormat("{1} - {2} at {3}{0}{4}", _

Environment.NewLine, _

"HouseKeepingScheduleMaint", _

Now.ToLongDateString, _

Now.ToShortTimeString, _

Message)

clsLOG.LogTMSEvent(LogMsg.ToString, UtilLogging.clsLogging.TMSLogType.TMSServices)

End Sub



'---------------------------------------------------------------

' Form Closing and Closed

' Note: the specific nature of Form Load precludes its inclusion here.



Private Sub ThisForm_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) _

Handles Me.FormClosed

Try

clsFU.HandleFormClosed(CType(sender, System.Windows.Forms.Form), e)

Catch ex As Exception

End Try

End Sub



Private Sub ThisForm_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) _

Handles Me.FormClosing



Try

If Me.BoSCH1.IsDirty Then

BoSCH1.Save()

End If

LogInfo("Restarting TMSHousekeepingService in frmSCH")

clsSSV.RestartService("TMSHousekeepingService")

LogInfo("Restarted TMSHousekeepingService in frmSCH")

clsFU.HandleFormClosing(CType(sender, System.Windows.Forms.Form), e)

Catch ex As Exception



End Try



End Sub



#End Region



End Class



Jeff Pagley
Jeff Pagley
StrataFrame User (465 reputation)StrataFrame User (465 reputation)StrataFrame User (465 reputation)StrataFrame User (465 reputation)StrataFrame User (465 reputation)StrataFrame User (465 reputation)StrataFrame User (465 reputation)StrataFrame User (465 reputation)StrataFrame User (465 reputation)
Group: StrataFrame Users
Posts: 223, Visits: 893
Peter,

Thanks so much for the info.  I will take a close look at what you are doing and try to implement it.  It is good to know someone has gotten this to work with SF BBS. 

Just to be clear about how your form is setup.  You have the scheduler storage and control objects, SF BO and SF BBS dropped on the form.  You have mapped the scheduler control fields to the BO fields.  Then you are managing the updates to the BO within the scheduler storage event handlers.  Am I correct on this?

Jeff

Peter Jones
Peter Jones
Advanced StrataFrame User (504 reputation)Advanced StrataFrame User (504 reputation)Advanced StrataFrame User (504 reputation)Advanced StrataFrame User (504 reputation)Advanced StrataFrame User (504 reputation)Advanced StrataFrame User (504 reputation)Advanced StrataFrame User (504 reputation)Advanced StrataFrame User (504 reputation)Advanced StrataFrame User (504 reputation)
Group: Forum Members
Posts: 386, Visits: 2.1K
Hi Jeff,



That's right. It was understanding the correct DX events to use was very problematic.



Cheers, Peter
Jéssica Neves
Jéssica Neves
StrataFrame Beginner (16 reputation)StrataFrame Beginner (16 reputation)StrataFrame Beginner (16 reputation)StrataFrame Beginner (16 reputation)StrataFrame Beginner (16 reputation)StrataFrame Beginner (16 reputation)StrataFrame Beginner (16 reputation)StrataFrame Beginner (16 reputation)StrataFrame Beginner (16 reputation)
Group: Forum Members
Posts: 14, Visits: 102
how to use business objects in xtra sheduling

I'm trying to appointments with Business Binding Source with DevExpress Scheduler / Calendar control

 
conssegui but I'm not someone help me?
  

 


Trent Taylor
Trent Taylor
StrataFrame Developer (10K reputation)StrataFrame Developer (10K reputation)StrataFrame Developer (10K reputation)StrataFrame Developer (10K reputation)StrataFrame Developer (10K reputation)StrataFrame Developer (10K reputation)StrataFrame Developer (10K reputation)StrataFrame Developer (10K reputation)StrataFrame Developer (10K reputation)
Group: StrataFrame Developers
Posts: 6.6K, Visits: 6.9K
It has been a while since I have looked at the DevExpress scheduler, but in this case, I sat down with Jeff when he came to class and showed him how to populate the business object and then manually populate the appointments on the scheduler.  I recall the direct binding to this control (outside of StrataFrame included) being a bit tricky with some strange side-effects.
Ivan George Borges
Ivan George Borges
Strategic Support Team Member (3.5K reputation)Strategic Support Team Member (3.5K reputation)Strategic Support Team Member (3.5K reputation)Strategic Support Team Member (3.5K reputation)Strategic Support Team Member (3.5K reputation)Strategic Support Team Member (3.5K reputation)Strategic Support Team Member (3.5K reputation)Strategic Support Team Member (3.5K reputation)Strategic Support Team Member (3.5K reputation)
Group: StrataFrame MVPs
Posts: 1.9K, Visits: 21K
Hi Jéssica.

Also, have a look at this post from Paul Chase and it might help you:

http://forum.strataframe.net/FindPost8050.aspx

Abraços.
GO

Merge Selected

Merge into selected topic...



Merge into merge target...



Merge into a specific topic ID...




Similar Topics

Reading This Topic

Login

Explore
Messages
Mentions
Search