Building Microsoft® Office® Inspired apps is a snap with DXperience 12.2. From Reporting Controls, Data Grids and Tree Lists to Schedulers, Ribbons and App Skins, the DXperience 12.2 offers a complete set of user interface controls to get you from A to Z in no time.
In previous sections we’ve created a Project Manager App where we can display and manage different kinds of projects and their inter dependencies. We’ve also created a Microsoft® Outlook® Style Task List to manage the tasks using the Data Grid Control. Let’s continue customizing the Data Grid and synchronize it with the Scheduler.
Task Grid Customization
Adding an image column to the Grid, is just a matter of adding an in-place editor. We’ll follow the same steps described in the previous article. The only difference would be the column type for the grid. The DevExpress XtraGrid Control fully supports the Unbound Column Types, and this is what we’ll use for our image columns.
Let’s drop an ImageList component onto our form and add the glyphs:
And using the Run Designer, create new column. Call it colTaskImage and set the UnboundType to Integer
Now assign a new ImageComboBoxEdit editor to this column,
set SmallImages property to point to the ImageList component,
and finally add one item to the Items collection.
Providing data to unbound columns is done using the CustomUnboundColumnData event
privatevoid tasksGridView_CustomUnboundColumnData(object sender, CustomColumnDataEventArgs e)
{
// Are we getting UnboundData or setting it?
if (e.IsGetData)
{
// Make sure there's a row - may be appending a new appointment
if (e.ListSourceRowIndex < dXProjectManagerDataSet.Appointments.Count)
{
// Is this our static task image column?
if (e.Column == colTaskImage)
{
// Always return 0 - there's only one image for this column
e.Value = 0;
}
}
}
}
Go ahead and run the app to see it in action.
Integrating Grid with Scheduler
The last thing we're going to do is integrate the DevExpress XtraGrid control together with the XtraScheduler. We’ll start by adding the following lines to the Form1_Load event handler implementation:
// Subscribe to evens on the XtraGrid and SchedulerControl to synchronize their selectionsSubscribeSelectionEvents();// Subscribe to selection changed events on the XtraGrid and SchedulerControlprivatevoid SubscribeSelectionEvents() { schedulerControl.SelectionChanged += schedulerControl_SelectionChanged; tasksGridView.SelectionChanged += tasksGridView_SelectionChanged; }// Unsubscribe from selection changed events on the XtraGrid and SchedulerControlprivatevoid UnsubscribeSelectionEvents() { schedulerControl.SelectionChanged -= schedulerControl_SelectionChanged; tasksGridView.SelectionChanged -= tasksGridView_SelectionChanged; } // SelectionChanged event for the SchedulerControl to synchronize with an XtraGridprivatevoid schedulerControl_SelectionChanged(object sender, EventArgs e) { UnsubscribeSelectionEvents(); tasksGridView.BeginSelection();try { tasksGridView.ClearSelection();for (int i = 0; i < schedulerControl.SelectedAppointments.Count; i++) SelectAppointmentInGrid(schedulerControl.SelectedAppointments[i]); }finally { tasksGridView.EndSelection(); SubscribeSelectionEvents(); } }// Select a scheduler appointment in the Tasks XtraGridprivatevoid SelectAppointmentInGrid(Appointment appointment) { DataRowView rowView = (DataRowView)appointment.GetSourceObject(schedulerStorage);if (rowView == null) {return; }int dataSourceIndex = dXProjectManagerDataSet.Appointments.Rows.IndexOf(rowView.Row);int rowHandle = tasksGridView.GetRowHandle(dataSourceIndex); tasksGridView.SelectRow(rowHandle); tasksGridView.MakeRowVisible(rowHandle, false); }// SelectionChanged event for the XtraGrid to synchronize with a SchedulerControlprivatevoid tasksGridView_SelectionChanged(object sender, SelectionChangedEventArgs e) { UnsubscribeSelectionEvents();try { DataRow[] gridRows = GetGridSelectedDataRows(); AppointmentBaseCollection aptsToSelect = GetAppointmentsForDataRows(gridRows); SelectAppointmentsInScheduler(aptsToSelect); }finally { SubscribeSelectionEvents(); } }// Get an array of DataRow corresponding to the selected rows in the XtraGridprivate DataRow[] GetGridSelectedDataRows() {int[] rowHandles = tasksGridView.GetSelectedRows(); DataRow[] rows = new DataRow[rowHandles.Length];for (int i = 0; i < rowHandles.Length; i++) rows[i] = tasksGridView.GetDataRow(rowHandles[i]);return rows; }// Get a colleciton of Appointment corresponding to an array of DataRowprivate AppointmentBaseCollection GetAppointmentsForDataRows(DataRow[] rows) { AppointmentBaseCollection appointments = new AppointmentBaseCollection();for (int i = 0; i < rows.Length; i++) { Appointment apt = appointmentRowHash[rows[i]] as Appointment;if (apt != null) appointments.Add(apt); }return appointments; }// Select each of the appointments in the collection in the SchedulerControlprivatevoid SelectAppointmentsInScheduler(AppointmentBaseCollection appointments) {if (appointments.Count <= 0)return; SchedulerViewBase view = schedulerControl.ActiveView; view.SelectAppointment(appointments[0]); schedulerControl.BeginUpdate(); try {for (int i = 1; i < appointments.Count; i++) view.AddAppointmentSelection(appointments[i]); } finally { schedulerControl.EndUpdate(); } }
Next, handle the events FilterAppointment, AppointmentCollectionCleared, and AppointmentCollectionAutoReloading on the schedulerStorage as follows:
// Collection used to map XtraScheduler Appointments to DataRows
readonly Hashtable appointmentRowHash = new Hashtable();
// Event handler that must be assigned on the schedulerStorage - used to build the above appointmentRowHash
privatevoid schedulerStorage_FilterAppointment(object sender, PersistentObjectCancelEventArgs e)
{
DataRowView rowView = (DataRowView)schedulerStorage.GetObjectRow(e.Object);
//could be a recurrence with no row
if (rowView == null)
{
return;
}
DataRow row = rowView.Row;
if (!appointmentRowHash.ContainsKey(row))
appointmentRowHash.Add(rowView.Row, e.Object);
}
// Event handler that must be assigned to schedulerStorage - clear the appointmentRowHash
privatevoid schedulerStorage_AppointmentCollectionCleared(object sender, EventArgs e)
{
appointmentRowHash.Clear();
}
// Event handler that must be assigned to schedulerStorage - clear the appointmentRowHash
privatevoid schedulerStorage_AppointmentCollectionAutoReloading(object sender, CancelListChangedEventArgs e)
{
appointmentRowHash.Clear();
}
Now, update the ShowResourceEditor() method by adding the following lines:
// Required to update the mappings in appointmentRowHash
appointmentsBindingSource.ResetBindings(false);
Download the Full Source Code