Scheduler for WPF and Silverlight | ComponentOne
Scheduler for Silverlight Tutorials / Creating a Custom Application for Custom Data / Step 3 of 5: Creating the Custom Appointment Dialog
In This Topic
    Step 3 of 5: Creating the Custom Appointment Dialog
    In This Topic

    In this step, you will create the Custom Appointment Dialog and set the code to control the dialog using XAML markup and code.

    1. Create a new Silverlight page by right-clicking the application name and selecting Add | New Item from the list.
    2. Select New Silverlight Page from the list of installed templates and name it EditAppointmentDialog. Click OK.
    3. Replace the <navigation:Page> </navigation:Page> tags and the namespaces with the following <UserControl> statement:

      XAML
      Copy Code
      <UserControl x:Class="SchedulerCustomData.EditAppointmentDialog"    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"           xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      xmlns:c1sched="clr-namespace:C1.Silverlight.Schedule;assembly=C1.Silverlight.Schedule"
      xmlns:c1="clr-namespace:C1.Silverlight;assembly=C1.Silverlight"
      xmlns:local="clr-namespace:SchedulerCustomData"
      mc:Ignorable="d"
      d:DesignHeight="300" d:DesignWidth="400">
      

    4. Insert the following XAML after the namespace declarations to create the custom Appointment dialog box:

      XAML
      Copy Code
      <Grid x:Name="LayoutRoot" Background="White" BindingValidationError="LayoutRoot_BindingValidationError">
              <Grid.Resources>
      <res:C1_Schedule_EditAppointment x:Key="C1_Schedule_EditAppointment"/>
              </Grid.Resources>
              <Grid.RowDefinitions>
                  <RowDefinition Height="Auto" />
                  <RowDefinition Height="Auto" />
                  <RowDefinition Height="Auto" />
                  <RowDefinition Height="Auto" />
                  <RowDefinition Height="Auto" />
                  <RowDefinition Height="Auto" />
                  <RowDefinition Height="Auto" />
                  <RowDefinition  />
                  <RowDefinition Height="Auto" />
              </Grid.RowDefinitions>
              <Grid>
                  <Grid.ColumnDefinitions>
                      <ColumnDefinition Width="75" />
                      <ColumnDefinition Width="*" />
                  </Grid.ColumnDefinitions>
      <TextBlock VerticalAlignment="Center" Margin="10,2,0,2" HorizontalAlignment="Left" Text="{Binding subject, Source={StaticResource C1_Schedule_EditAppointment}}" />
      <TextBox x:Name="subject" Grid.Column="1" TabIndex="0" Padding="2" Text="{Binding Subject, Mode=TwoWay}" TextChanged="subject_TextChanged" MaxLength="255" VerticalAlignment="Center" Margin="10,2,10,2" />
              </Grid>
              <Grid Grid.Row="1">
                  <Grid.ColumnDefinitions>
                      <ColumnDefinition Width="75" />
                      <ColumnDefinition Width="*" />
                  </Grid.ColumnDefinitions>
              <TextBlock VerticalAlignment="Center" Margin="10,2,0,2" HorizontalAlignment="Left" Text="{Binding location, Source={StaticResource C1_Schedule_EditAppointment}}" />
      <TextBox TabIndex="1" x:Name="location" Grid.Column="1" Text="{Binding Location, Mode=TwoWay}" MaxLength="255" VerticalAlignment="Center" Margin="10,2,10,2" />
              </Grid>
              <Grid Grid.Row="2">
                  <Grid.ColumnDefinitions>
                      <ColumnDefinition Width="75" />
                      <ColumnDefinition Width="*" />
                  </Grid.ColumnDefinitions>
       <TextBlock VerticalAlignment="Center" Margin="10,2,0,2" HorizontalAlignment="Left" Text="{Binding startTime, Source={StaticResource C1_Schedule_EditAppointment}}"/>
      <c1datetime:C1DateTimePicker x:Name="startCalendar" Grid.Column="1" VerticalAlignment="Center" Margin="10,2,10,2"        Padding="1" IsTabStop="False" TimeFormat="ShortTime" DateFormat="Long" FirstDayOfWeek="{Binding Path=ParentCollection.ParentStorage.ScheduleStorage.Scheduler.CalendarHelper.WeekStart}" DateTime="{Binding Start, Mode=TwoWay}"/>
              </Grid>
              <Grid Grid.Row="3">
                  <Grid.ColumnDefinitions>
                      <ColumnDefinition Width="75" />
                      <ColumnDefinition Width="*" />
                  </Grid.ColumnDefinitions>
       <TextBlock VerticalAlignment="Center" Margin="10,2,0,2" HorizontalAlignment="Left" Text="{Binding endTime, Source={StaticResource C1_Schedule_EditAppointment}}"/>
      <c1datetime:C1DateTimePicker x:Name="endCalendar" VerticalAlignment="Center" Margin="10,2,10,2" Padding="1" DateTimeChanged="endCalendar_DateTimeChanged" FirstDayOfWeek="{Binding Path=ParentCollection.ParentStorage.ScheduleStorage.Scheduler.CalendarHelper.WeekStart}" TimeFormat="ShortTime" DateFormat="Long" Grid.Column="1" c1:C1NagScreen.Nag="True" />
              </Grid>
              <Grid Grid.Row="4" Background="Yellow">
                  <Grid.ColumnDefinitions>
                      <ColumnDefinition Width="100" />
                      <ColumnDefinition Width="*" />
                  </Grid.ColumnDefinitions>
      <TextBlock VerticalAlignment="Center" Text="Custom Data:" HorizontalAlignment="Left" Margin="10,2,0,2"/>
      <TextBox Name="customDataTextBox" Grid.Column="1" Text="{Binding Path=CustomData, Mode=TwoWay}" Margin="10,2,10,2"/>
              </Grid>
              <Grid Grid.Row="5" Background="Orange">
                  <Grid.ColumnDefinitions>
                      <ColumnDefinition Width="100" />
                      <ColumnDefinition Width="*" />
                  </Grid.ColumnDefinitions>
      <TextBlock VerticalAlignment="Center" Text="BO Property 1:" HorizontalAlignment="Left" Margin="10,2,0,2"/>
      <TextBox Name="BOTextBox1" Grid.Column="1" Text="{Binding Path=Tag.Tag.BOProperty1, Mode=TwoWay}" Margin="10,2,10,2" />
              </Grid>
              <Grid Grid.Row="6" Background="Orange">
                  <Grid.ColumnDefinitions>
                      <ColumnDefinition Width="100" />
                      <ColumnDefinition Width="*" />
                  </Grid.ColumnDefinitions>
      
      <TextBlock VerticalAlignment="Center" Text="BO Property 2:" HorizontalAlignment="Left" Margin="10,2,0,2"/>
      <TextBox Name="BOTextBox2" Grid.Column="1" Text="{Binding Path=Tag.Tag.BOProperty2, Mode=TwoWay}" Margin="10,2,10,2"/>
              </Grid>
              <Grid Grid.Row="7">
                  <Grid.ColumnDefinitions>
                      <ColumnDefinition Width="75" />
                      <ColumnDefinition Width="*" />
                  </Grid.ColumnDefinitions>
      <TextBlock VerticalAlignment="Top" Text="Notes:" HorizontalAlignment="Left" Margin="10,2,0,2"/>
      <TextBox x:Name="body" Text="{Binding Body, Mode=TwoWay}" AcceptsReturn="true" Grid.Column="1" Margin="10,2,10,2" />
              </Grid>
      <StackPanel Orientation="Horizontal" Grid.Row="8" HorizontalAlignment="Right">
      <Button Name="deleteButton" IsTabStop="False"  Margin="0,0,5,0"                        c1:CommandExtensions.CommandTarget="{Binding ParentCollection.ParentStorage.ScheduleStorage.Scheduler}" c1:CommandExtensions.CommandParameter="{Binding Tag}" c1:CommandExtensions.Command="c1sched:C1Scheduler.DeleteAppointmentCommand"                      ToolTipService.ToolTip="{Binding deleteButton_ToolTip, Source={StaticResource C1_Schedule_EditAppointment}}">
      <StackPanel Orientation="Horizontal" VerticalAlignment="Center">
      <Image Height="16" Width="16" Source="/SchedulerCustomData;component/Images/Delete.png"></Image>
        <TextBlock Text="Cancel Appointment" />
                      </StackPanel>
                  </Button>
       <Button x:Name="PART_DialogSaveButton" IsTabStop="False"  Click="PART_DialogSaveButton_Click"       ToolTipService.ToolTip="{Binding PART_DialogSaveButton_Tooltip, Source={StaticResource C1_Schedule_EditAppointment}}">
      <StackPanel Orientation="Horizontal" VerticalAlignment="Center">
       <Image Height="16" Width="16" Source="/SchedulerCustomData;component/Images/save.png"></Image>
      <TextBlock Margin="3,0,0,0" Text="{Binding PART_DialogSaveButton_AccessText, Source={StaticResource C1_Schedule_EditAppointment}}" VerticalAlignment="Center"/>                </StackPanel>
      </Button>      
      </StackPanel>
          </Grid>
      </UserControl>
      

       The Edit Appointment dialog box in Design View should resemble the following image:

       

       

    5. Right-click on the page and select View Code from the list. In Code View, add the following namespaces to the application:

      Visual Basic
      Copy Code
      Imports C1.Silverlight.Schedule
      Imports C1.Silverlight
      Imports C1.Silverlight.DateTimeEditors
      Imports C1.C1Schedule
      Imports System.Windows.Data
      

      C#
      Copy Code
      using C1.Silverlight.Schedule;
      using C1.Silverlight;
      using C1.Silverlight.DateTimeEditors;
      using C1.C1Schedule;
      using System.Windows.Data;
      

    6. Add the following region directive and public method below the public partial class:

      VIsual Basic
      Copy Code
      #Region "fields"
          Dim _parentWindow As ContentControl = Nothing
          Dim _appointment As Appointment
          Dim _scheduler As C1Scheduler
      #End Region
      

      C#
      Copy Code
      #region ** fields
              private ContentControl _parentWindow = null;
              private Appointment _appointment;
              //AppointmentBORow customBO; //not used
              private C1Scheduler _scheduler;
              #endregion
      

    7. Add a UserControl_Loaded event handler:

      Visual Basic
      Copy Code
      Private Sub UserControl_Loaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
              _appointment = CType(DataContext, Appointment)
              'Appointment sourceApp = _appointment.Tag As Appointment
              'customBO = sourceApp.Tag As AppointmentBORow
              _parentWindow = CType(VTreeHelper.GetParentOfType(Me, GetType(C1Window)), ContentControl)
              If (Not (_parentWindow) Is Nothing) Then
                  Dim bnd As Binding = New Binding("Header")
                  bnd.Source = Me
                  _parentWindow.SetBinding(C1Window.HeaderProperty, bnd)
              End If
              If (Not (_appointment) Is Nothing) Then
                  AddHandler CType(_appointment, System.ComponentModel.INotifyPropertyChanged).PropertyChanged, AddressOf Me.appointment_PropertyChanged
                  If (Not (_appointment.ParentCollection) Is Nothing) Then
                      _scheduler = _appointment.ParentCollection.ParentStorage.ScheduleStorage.Scheduler
                  End If
                  Header = "Edit Appointment"
                  UpdateEndCalendar()
                  endCalendar.EditMode = C1DateTimePickerEditMode.DateTime
                  startCalendar.EditMode = C1DateTimePickerEditMode.DateTime
              End If
              subject.Focus()
          End Sub
      

       

      C#
      Copy Code
       private void UserControl_Loaded(object sender, RoutedEventArgs e)
              {
                  _appointment = DataContext as Appointment;
                  //Appointment sourceApp = _appointment.Tag as Appointment;
                  //customBO = sourceApp.Tag as AppointmentBORow;
      
                  _parentWindow = (ContentControl)VTreeHelper.GetParentOfType(this, typeof(C1Window));
                  if (_parentWindow != null)
                  {
                      Binding bnd = new Binding("Header");
                      bnd.Source = this;
                      _parentWindow.SetBinding(C1Window.HeaderProperty, bnd);
                  }
                  if (_appointment != null)
                  {
                      ((System.ComponentModel.INotifyPropertyChanged)_appointment).PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(appointment_PropertyChanged);
                      if (_appointment.ParentCollection != null)
                      {
                          _scheduler = _appointment.ParentCollection.ParentStorage.ScheduleStorage.Scheduler;
                      }
                      Header = "Edit Appointment";
                      UpdateEndCalendar();
                      startCalendar.EditMode = endCalendar.EditMode = C1DateTimePickerEditMode.DateTime;
                  }
                  subject.Focus();
              }
      

    8. Add the following code to govern some of the button and mouse events:

      Visual Basic
      Copy Code
      Protected Overrides Sub OnMouseEnter(ByVal e As MouseEventArgs)
              MyBase.OnMouseEnter(e)
          End Sub
      
          Protected Overrides Sub OnGotFocus(ByVal e As RoutedEventArgs)
              MyBase.OnGotFocus(e)
          End Sub
      
          Private Sub LayoutRoot_BindingValidationError(ByVal sender As Object, ByVal e As ValidationErrorEventArgs)
              If (e.Action = ValidationErrorEventAction.Added) Then
                  PART_DialogSaveButton.IsEnabled = False
                  PART_DialogSaveButton.IsEnabled = False
              Else
                  PART_DialogSaveButton.IsEnabled = True
              End If
          End Sub
      
          Private Sub PART_DialogSaveButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
              SetAppointment()
              CType(_parentWindow, C1Window).DialogResult = MessageBoxResult.OK
          End Sub
      
          Private Sub subject_TextChanged(ByVal sender As Object, ByVal e As TextChangedEventArgs)
              subject.GetBindingExpression(TextBox.TextProperty).UpdateSource()
          End Sub
      

      C#
      Copy Code
      protected override void OnMouseEnter(MouseEventArgs e)
              {
                  base.OnMouseEnter(e);
              }
              protected override void OnGotFocus(RoutedEventArgs e)
              {
                  base.OnGotFocus(e);
              }
              private void LayoutRoot_BindingValidationError(object sender, ValidationErrorEventArgs e)
              {
                  if (e.Action == ValidationErrorEventAction.Added)
                  {
                      PART_DialogSaveButton.IsEnabled = false;
                  }
                  else
                  {
                      PART_DialogSaveButton.IsEnabled = true;
                  }
              }
              private void PART_DialogSaveButton_Click(object sender, RoutedEventArgs e)
              {
                  SetAppointment();
                  ((C1Window)_parentWindow).DialogResult = MessageBoxResult.OK;
              }
              private void subject_TextChanged(object sender, TextChangedEventArgs e)
              {          subject.GetBindingExpression(TextBox.TextProperty).UpdateSource();
              }
      

    9. Add the SetAppointment method :

      Visual Basic
      Copy Code
      Private Sub SetAppointment()
              location.GetBindingExpression(TextBox.TextProperty).UpdateSource()
              body.GetBindingExpression(TextBox.TextProperty).UpdateSource()
              'Update Additional Data Properties      
              customDataTextBox.GetBindingExpression(TextBox.TextProperty).UpdateSource()
              BOTextBox1.GetBindingExpression(TextBox.TextProperty).UpdateSource()
              BOTextBox2.GetBindingExpression(TextBox.TextProperty).UpdateSource()
          End Sub
      
          Private Sub appointment_PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs)
              UpdateEndCalendar()
          End Sub
      

      C#
      Copy Code
      private void SetAppointment()
              {            location.GetBindingExpression(TextBox.TextProperty).UpdateSource();            body.GetBindingExpression(TextBox.TextProperty).UpdateSource();
                  //Update Additional Data Properties            customDataTextBox.GetBindingExpression(TextBox.TextProperty).UpdateSource();            BOTextBox1.GetBindingExpression(TextBox.TextProperty).UpdateSource();            BOTextBox2.GetBindingExpression(TextBox.TextProperty).UpdateSource();
              }
              void appointment_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
              {
                  UpdateEndCalendar();
              }
      

    10. Add the following object model to the EditAppointmentDialog class:

      Visual Basic
      Copy Code
      #Region "Appointment Properties"
          Public Property Appointment As Appointment
              Get
                  Return _appointment
              End Get
              Set(value As Appointment)
                  _appointment = value
                  If (Not (_parentWindow) Is Nothing) Then
                      _parentWindow.DataContext = value
                      _parentWindow.Content = value
                  End If
                  DataContext = value
              End Set
          End Property
          ''' <summary>
          ''' Gets a <see cref="String"/> value which can be used as an Appointment window header.
          ''' </summary>
          Public Property Header As String
              Get
                  Return CType(GetValue(HeaderProperty), String)
              End Get
              Set(value As String)
                  SetValue(HeaderProperty, value)
              End Set
          End Property
          Private Shared HeaderProperty As DependencyProperty = DependencyProperty.Register("Header", GetType(System.String), GetType(EditAppointmentDialog), Nothing)
          ''' <summary>
          ''' Gets recurrence pattern description.
          ''' </summary>
          Public Property PatternDescription As String
              Get
                  Return CType(GetValue(PatternDescriptionProperty), String)
              End Get
              Set(value As String)
                  SetValue(PatternDescriptionProperty, value)
              End Set
          End Property
          Public Shared PatternDescriptionProperty As DependencyProperty = DependencyProperty.Register("PatternDescription", GetType(System.String), GetType(EditAppointmentControl), New PropertyMetadata(String.Empty))
      #End Region
      

      C#
      Copy Code
      #region ** object model
              /// <summary>
              /// Gets an <see cref="Appointment"/> object representing current DataContext.
              /// </summary>
              public Appointment Appointment
              {
                  get
                  {
                      return _appointment;
                  }
                  set
                  {
                      _appointment = value;
                      if (_parentWindow != null)
                      {
                          _parentWindow.Content =
                          _parentWindow.DataContext = value;
                      }
                      DataContext = value;
                  }
              }
              /// <summary>
              /// Gets a <see cref="String"/> value which can be used as an Appointment window header.
              /// </summary>
              public string Header
              {
                  get { return (string)GetValue(HeaderProperty); }
                  private set { SetValue(HeaderProperty, value); }
              }
              private static readonly DependencyProperty HeaderProperty =
                  DependencyProperty.Register("Header", typeof(string), typeof(EditAppointmentDialog), null);
              /// <summary>
              /// Gets recurrence pattern description.
              /// </summary>
              public string PatternDescription
              {
                  get { return (string)GetValue(PatternDescriptionProperty); }
                  private set { SetValue(PatternDescriptionProperty, value); }
              }
              public static readonly DependencyProperty PatternDescriptionProperty =
                  DependencyProperty.Register("PatternDescription", typeof(string),
                  typeof(EditAppointmentControl), new PropertyMetadata(string.Empty));
              #endregion
      

    11. Insert the last portion of code to control the DateTimeChanged method:

      Visual Basic
      Copy Code
      #Region "DateTime Picker logic"
          Private Sub endCalendar_DateTimeChanged(ByVal sender As Object, ByVal e As NullablePropertyChangedEventArgs(Of DateTime))
              If (Not (_appointment) Is Nothing) Then
                  Dim dt As DateTime = endCalendar.DateTime.Value
                  If _appointment.AllDayEvent Then
                      dt = dt.AddDays(1)
                  End If
                  If (dt < Appointment.Start) Then
                      endCalendar.Background = New SolidColorBrush(Colors.Red)
                      endCalendar.Foreground = New SolidColorBrush(Colors.Red)
                      endCalendar.BorderBrush = New SolidColorBrush(Colors.Red)
                      endCalendar.BorderThickness = New Thickness(2)
                      ToolTipService.SetToolTip(endCalendar, C1.Silverlight.Schedule.Resources.C1_Schedule_Exceptions.StartEndValidationFailed)
                      PART_DialogSaveButton.IsEnabled = False
                  Else
                      _appointment.End = dt
                      If Not PART_DialogSaveButton.IsEnabled Then
                          PART_DialogSaveButton.IsEnabled = True
                          endCalendar.ClearValue(Control.BackgroundProperty)
                          endCalendar.ClearValue(Control.ForegroundProperty)
                          endCalendar.ClearValue(Control.BorderBrushProperty)
                          endCalendar.ClearValue(Control.BorderThicknessProperty)
                          endCalendar.ClearValue(ToolTipService.ToolTipProperty)
                      End If
                  End If
              End If
          End Sub
          Private Sub UpdateEndCalendar()
              Dim dt As DateTime = _appointment.End
              If _appointment.AllDayEvent Then
                  dt = dt.AddDays(-1)
              End If
              endCalendar.DateTime = dt
              If Not PART_DialogSaveButton.IsEnabled Then
                  PART_DialogSaveButton.IsEnabled = True
                  endCalendar.ClearValue(Control.BackgroundProperty)
                  endCalendar.ClearValue(Control.ForegroundProperty)
                  endCalendar.ClearValue(Control.BorderBrushProperty)
                  endCalendar.ClearValue(Control.BorderThicknessProperty)
                  endCalendar.ClearValue(ToolTipService.ToolTipProperty)
              End If
          End Sub
      #End Region
      

      C#
      Copy Code
      #region "DateTime Picker logic"
              private void endCalendar_DateTimeChanged(object sender, NullablePropertyChangedEventArgs<DateTime> e)
              {
                  if (_appointment != null)
                  {
                      DateTime end = endCalendar.DateTime.Value;
                      if (_appointment.AllDayEvent)
                      {
                          end = end.AddDays(1);
                      }
                      if (end < Appointment.Start)
                      {
                          endCalendar.BorderBrush = endCalendar.Foreground =
                          endCalendar.Background = new SolidColorBrush(Colors.Red);
                          endCalendar.BorderThickness = new Thickness(2);
                          ToolTipService.SetToolTip(endCalendar,                        C1.Silverlight.Schedule.Resources.C1_Schedule_Exceptions.StartEndValidationFailed);
                          PART_DialogSaveButton.IsEnabled = false;
                      }
                      else
                      {
                          _appointment.End = end;
                          if (!PART_DialogSaveButton.IsEnabled)
                          {
                              PART_DialogSaveButton.IsEnabled = true;                        endCalendar.ClearValue(Control.BackgroundProperty);                        endCalendar.ClearValue(Control.ForegroundProperty);                        endCalendar.ClearValue(Control.BorderBrushProperty);                        endCalendar.ClearValue(Control.BorderThicknessProperty);                        endCalendar.ClearValue(ToolTipService.ToolTipProperty);
                          }
                      }
                  }
              }
              private void UpdateEndCalendar()
              {
                  DateTime end = _appointment.End;
                  if (_appointment.AllDayEvent)
                  {
                      end = end.AddDays(-1);
                  }
                  endCalendar.DateTime = end;
                  if (!PART_DialogSaveButton.IsEnabled)
                  {
                      PART_DialogSaveButton.IsEnabled = true;
                      endCalendar.ClearValue(Control.BackgroundProperty);
                      endCalendar.ClearValue(Control.ForegroundProperty);
                      endCalendar.ClearValue(Control.BorderBrushProperty);                endCalendar.ClearValue(Control.BorderThicknessProperty);                endCalendar.ClearValue(ToolTipService.ToolTipProperty);
                  }
              }
              #endregion
          }
      }
      

      In this step, you created the custom Edit Appointment dialog box and set the code to control the appointment methods and events.