Outlook Calendar Code Mofications

Coordinator
Oct 19, 2009 at 8:37 PM

Im starting a new thread for code modifcations to the Outlook Calendar.

Coordinator
Oct 19, 2009 at 8:38 PM
Edited Oct 19, 2009 at 8:48 PM

Updating current thread with previous code modifcations...

Coordinator
Oct 19, 2009 at 8:39 PM
Edited Oct 19, 2009 at 8:40 PM

from ttschupp:

It is the amount of minues each content item takes up. It has to be dividisible evenly in to an hour. In Outlook it allows 5, 6, 10, 15, 20, 30 and 60 minutes. Instead of splitting each hour into parts by an even number, you would split

it by minutes that divides evenly into an hour. I would say 5 , 6, 10, 15, 30, 60 is enough and if a user enters anything else, you would round up or down to the closest number in the set.

I modified the folowing code in the TimeSlot provider:

TimeSpan tsStart = new TimeSpan(0, 0, 0);
TimeSpan tsEnd = new TimeSpan(24, 0, 0);
TimeSpan tsTimeScale = new TimeSpan(0, 15, 0);

            while (tsStart < tsEnd)
            {
                TimeSlot ucTs = new TimeSlot();
                if(tsStart.Minutes==0)
                {
                    switch (tsStart.Hours)
                    {
                        case 0:
                            ucTs.Hour = "12";
                            ucTs.Minute = "AM";
                            break;
                        case 12:
                            ucTs.Hour = "12";
                            ucTs.Minute = "PM";
                            break;
                        default:
                            if (tsStart.Hours > 12)
                            {
                                ucTs.Hour = (tsStart.Hours - 12).ToString();
                                ucTs.Minute = "00";
                            }
                            else
                            {
                                ucTs.Hour = tsStart.Hours.ToString();
                                ucTs.Minute = "00";
                            }
                            break;
                    }
                    HourIsNowTime(ref ucTs, tsStart.Hours);
                }
               
              
               this.Add(ucTs);

                tsStart += tsTimeScale;
            }

Coordinator
Oct 19, 2009 at 8:41 PM
Edited Oct 19, 2009 at 8:51 PM

from ttschupp:
Today at 2:31 PM
Edited Today at 2:33 PM

I did some code modification to get double click working. I now have the Add Appointment event being called when a double click is registered. I am determining the best way to do the select event, but in order to start on it, I need to get the single click reserved for it since it was being used to fire the add appointment event.

ucDayContentItem.cs

Added new namespace for DispatcherTimer, code for doubleclick

 

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using SLControlLibrary.Resources.Controls.OutlookCalendar.BusinessObjects;
using System.Windows.Threading;

namespace SLControlLibrary.Resources.Controls.OutlookCalendar
{
    public class ucDayContentItem : Control
    {
        #region Dependency Variables
        private static readonly DependencyProperty MouseOverOpacityProperty = DependencyProperty.Register("MouseOverOpacity", typeof(double), typeof(ucDayContentItem), new PropertyMetadata(0D));
        private static readonly DependencyProperty HasAppointmentProperty = DependencyProperty.Register("HasAppointment", typeof(Visibility), typeof(ucDayContentItem), new PropertyMetadata(Visibility.Visible));
        private static readonly DependencyProperty IsAppointmentProperty = DependencyProperty.Register("IsAppointment", typeof(Visibility), typeof(ucDayContentItem), new PropertyMetadata(Visibility.Collapsed));
        private static readonly DependencyProperty DescProperty = DependencyProperty.Register("Desc", typeof(string), typeof(ucDayContentItem), new PropertyMetadata("Not so Happy"));
        private static readonly DependencyProperty DayContentForegroundProperty = DependencyProperty.Register("DayContentForeground", typeof(Brush), typeof(ucDayContentItem), new PropertyMetadata(new SolidColorBrush(Colors.White), new PropertyChangedCallback(DayContentForeground_Changed)));
        private static readonly DependencyProperty DayContentHoverBorderBrushProperty = DependencyProperty.Register("DayContentHoverBorderBrush", typeof(Brush), typeof(ucDayContentItem), new PropertyMetadata(SLControlLibrary.Resources.Common.Utility.ConvertStringToColor("#5D8CC9"), new PropertyChangedCallback(DayContentHoverBorderBrush_Changed)));
        private static readonly DependencyProperty DayContentHoverBackgroundProperty = DependencyProperty.Register("DayContentHoverBackground", typeof(Brush), typeof(ucDayContentItem), new PropertyMetadata(SLControlLibrary.Resources.Common.Utility.ConvertStringToColor("#10000000"), new PropertyChangedCallback(DayContentHoverBackground_Changed)));
        private static readonly DependencyProperty DayContentHoverBorderThicknessProperty = DependencyProperty.Register("DayContentHoverBorderThickness", typeof(Thickness), typeof(ucDayContentItem), new PropertyMetadata(new Thickness(1), new PropertyChangedCallback(DayContentHoverBorderThickness_Changed)));
        private static readonly DependencyProperty DayAppointmentForegroundProperty = DependencyProperty.Register("DayAppointmentForeground", typeof(Brush), typeof(ucDayContentItem), new PropertyMetadata(new SolidColorBrush(Colors.White), new PropertyChangedCallback(DayAppointmentForeground_Changed)));
        private static readonly DependencyProperty DayAppointmentBackgroundProperty = DependencyProperty.Register("DayAppointmentBackground", typeof(Brush), typeof(ucDayContentItem), new PropertyMetadata(SLControlLibrary.Resources.Common.Utility.ConvertStringToColor("#10000000"), new PropertyChangedCallback(DayAppointmentBackground_Changed)));
        private static readonly DependencyProperty DayAppointmentBorderBrushProperty = DependencyProperty.Register("DayAppointmentBorderBrush", typeof(Brush), typeof(ucDayContentItem), new PropertyMetadata(SLControlLibrary.Resources.Common.Utility.ConvertStringToColor("#5D8CC9"), new PropertyChangedCallback(DayAppointmentBorderBrush_Changed)));
        private static readonly DependencyProperty DayAppointmentBorderThicknessProperty = DependencyProperty.Register("DayAppointmentBorderThickness", typeof(Thickness), typeof(ucDayContentItem), new PropertyMetadata(new Thickness(1), new PropertyChangedCallback(DayAppointmentBorderThickness_Changed)));

        public static readonly DependencyProperty CurrentAppointmentProperty = DependencyProperty.Register("CurrentAppointment", typeof(Appointment), typeof(ucDayContentItem), new PropertyMetadata(null, new PropertyChangedCallback(CurrentAppointment_Changed)));
        #endregion

        #region Dependency Properties
        public double MouseOverOpacity
        {
            get { return double.Parse(this.GetValue(MouseOverOpacityProperty).ToString()); }
            set { this.SetValue(MouseOverOpacityProperty, value); }
        }
        public Visibility HasAppointment
        {
            get { return (Visibility)this.GetValue(HasAppointmentProperty); }
            set { this.SetValue(HasAppointmentProperty, value); }
        }
        public Visibility IsAppointment
        {
            get { return (Visibility)this.GetValue(IsAppointmentProperty); }
            set { this.SetValue(IsAppointmentProperty, value); }
        }
        public string Desc
        {
            get { return this.GetValue(DescProperty).ToString(); }
            set { this.SetValue(DescProperty, value); }
        }
        public Brush DayContentForeground
        {
            get { return (Brush)this.GetValue(DayContentForegroundProperty); }
            set { this.SetValue(DayContentForegroundProperty, value); }
        }
        public Brush DayContentHoverBorderBrush
        {
            get { return (Brush)this.GetValue(DayContentHoverBorderBrushProperty); }
            set { this.SetValue(DayContentHoverBorderBrushProperty, value); }
        }
        public Brush DayContentHoverBackground
        {
            get { return (Brush)this.GetValue(DayContentHoverBackgroundProperty); }
            set { this.SetValue(DayContentHoverBackgroundProperty, value); }
        }
        public Thickness DayContentHoverBorderThickness
        {
            get { return (Thickness)this.GetValue(DayContentHoverBorderThicknessProperty); }
            set { this.SetValue(DayContentHoverBorderThicknessProperty, value); }
        }
        public Brush DayAppointmentForeground
        {
            get { return (Brush)this.GetValue(DayAppointmentForegroundProperty); }
            set { this.SetValue(DayAppointmentForegroundProperty, value); }
        }
        public Brush DayAppointmentBackground
        {
            get { return (Brush)this.GetValue(DayAppointmentBackgroundProperty); }
            set { this.SetValue(DayAppointmentBackgroundProperty, value); }
        }
        public Brush DayAppointmentBorderBrush
        {
            get { return (Brush)this.GetValue(DayAppointmentBorderBrushProperty); }
            set { this.SetValue(DayAppointmentBorderBrushProperty, value); }
        }
        public Thickness DayAppointmentBorderThickness
        {
            get { return (Thickness)this.GetValue(DayAppointmentBorderThicknessProperty); }
            set { this.SetValue(DayAppointmentBorderThicknessProperty, value); }
        }
        public Appointment CurrentAppointment
        {
            get { return (Appointment)this.GetValue(CurrentAppointmentProperty); }
            set { this.SetValue(CurrentAppointmentProperty, value); }
        }
        #endregion

        #region Dependency Events
        #region DayContentForeground_Changed
        private static void DayContentForeground_Changed(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            (sender as ucDayContentItem).OnDayContentForeground_Changed(e);
        }
        #endregion

        #region DayContentHoverBorderBrush_Changed
        private static void DayContentHoverBorderBrush_Changed(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            (sender as ucDayContentItem).OnDayContentHoverBorderBrush_Changed(e);
        }
        #endregion

        #region DayContentHoverBackground_Changed
        private static void DayContentHoverBackground_Changed(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            (sender as ucDayContentItem).OnDayContentHoverBackground_Changed(e);
        }
        #endregion

        #region DayContentHoverBorderThickness_Changed
        private static void DayContentHoverBorderThickness_Changed(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            (sender as ucDayContentItem).OnDayContentHoverBorderThickness_Changed(e);
        }
        #endregion

        #region DayAppointmentForeground_Changed
        private static void DayAppointmentForeground_Changed(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            (sender as ucDayContentItem).OnDayAppointmentForeground_Changed(e);
        }
        #endregion

        #region DayAppointmentBackground_Changed
        private static void DayAppointmentBackground_Changed(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            (sender as ucDayContentItem).OnDayAppointmentBackground_Changed(e);
        }
        #endregion

        #region DayAppointmentBorderBrush_Changed
        private static void DayAppointmentBorderBrush_Changed(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            (sender as ucDayContentItem).OnDayAppointmentBorderBrush_Changed(e);
        }
        #endregion

        #region DayAppointmentBorderThickness_Changed
        private static void DayAppointmentBorderThickness_Changed(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            (sender as ucDayContentItem).OnDayAppointmentBorderThickness_Changed(e);
        }
        #endregion

        #region CurrentAppointment_Changed
        private static void CurrentAppointment_Changed(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            (sender as ucDayContentItem).OnCurrentAppointment_Changed(e);
        }
        #endregion
        #endregion

        #region Variables
        private Border brdRoot = null;
        private DispatcherTimer _doubleClickTimer = null;
        #endregion

        #region Event Variables
        public event EventHandler Appointment_Clicked;
        public event EventHandler AddAppointment_Clicked;
        #endregion

        #region Constructor
        public ucDayContentItem()
        {


            DefaultStyleKey = typeof(ucDayContentItem);
        }
        #endregion

        #region Methods
        #region OnApplyTemplate
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            brdRoot = (Border)base.GetTemplateChild("brdRoot");

            if (brdRoot == null) return;

            _doubleClickTimer = new DispatcherTimer();
            _doubleClickTimer.Interval = new TimeSpan(0, 0, 0, 0, 200);
            _doubleClickTimer.Tick += new EventHandler(_doubleClickTimer_Tick);

            brdRoot.MouseEnter += new MouseEventHandler(brdRoot_MouseEnter);
            brdRoot.MouseLeave += new MouseEventHandler(brdRoot_MouseLeave);
            brdRoot.MouseLeftButtonDown += new MouseButtonEventHandler(brdRoot_MouseLeftButtonDown);
            
            
        }

        void _doubleClickTimer_Tick(object sender, EventArgs e)
        {
            _doubleClickTimer.Stop();
        }

        void brdRoot_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (_doubleClickTimer.IsEnabled)
            {
                this.Background = new SolidColorBrush(Colors.Green);
                AddAppointment_Clicked(this, null);
            }
            else
            {
                this.Background = new SolidColorBrush(Colors.Orange);
                _doubleClickTimer.Start();
            }
        }
        #endregion

        #region OnDayContentForeground_Changed
        protected virtual void OnDayContentForeground_Changed(DependencyPropertyChangedEventArgs e)
        {
            DayContentForeground = (Brush)e.NewValue;
        }
        #endregion

        #region OnDayContentHoverBorderBrush_Changed
        protected virtual void OnDayContentHoverBorderBrush_Changed(DependencyPropertyChangedEventArgs e)
        {
            DayContentHoverBorderBrush = (Brush)e.NewValue;
        }
        #endregion

        #region OnDayContentHoverBackground_Changed
        protected virtual void OnDayContentHoverBackground_Changed(DependencyPropertyChangedEventArgs e)
        {
            DayContentHoverBackground = (Brush)e.NewValue;
        }
        #endregion

        #region OnDayContentHoverBorderThickness_Changed
        protected virtual void OnDayContentHoverBorderThickness_Changed(DependencyPropertyChangedEventArgs e)
        {
            DayContentHoverBorderThickness = (Thickness)e.NewValue;
        }
        #endregion

        #region OnDayAppointmentForeground_Changed
        protected virtual void OnDayAppointmentForeground_Changed(DependencyPropertyChangedEventArgs e)
        {
            DayAppointmentForeground = (Brush)e.NewValue;
        }
        #endregion

        #region OnDayAppointmentBackground_Changed
        protected virtual void OnDayAppointmentBackground_Changed(DependencyPropertyChangedEventArgs e)
        {
            DayAppointmentBackground = (Brush)e.NewValue;
        }
        #endregion

        #region OnDayAppointmentBorderBrush_Changed
        protected virtual void OnDayAppointmentBorderBrush_Changed(DependencyPropertyChangedEventArgs e)
        {
            DayAppointmentBorderBrush = (Brush)e.NewValue;
        }
        #endregion

        #region OnDayAppointmentBorderThickness_Changed
        protected virtual void OnDayAppointmentBorderThickness_Changed(DependencyPropertyChangedEventArgs e)
        {
            DayAppointmentBorderThickness = (Thickness)e.NewValue;
        }
        #endregion

        #region OnCurrentAppointment_Changed
        protected virtual void OnCurrentAppointment_Changed(DependencyPropertyChangedEventArgs e)
        {
            CurrentAppointment = (Appointment)e.NewValue;
            Desc = CurrentAppointment.Desc;
        }
        #endregion
        #endregion

        #region Events
        #region brdRoot_MouseLeave
        private void brdRoot_MouseLeave(object sender, MouseEventArgs e)
        {
            MouseOverOpacity = 0;
        }
        #endregion

        #region brdRoot_MouseEnter
        private void brdRoot_MouseEnter(object sender, MouseEventArgs e)
        {
            //MouseOverOpacity = 1;
        }
        #endregion

        #endregion
    }
}


Coordinator
Oct 19, 2009 at 9:02 PM

I believe I understand the purpose behind the doubleclick but why do you need a timer on this?  A good way to pull out the single click is to get exclusive rights to the daycontentitem (i.e. if the item has an
exiting appointment then the single click will display it but if it does not then the doubleclick will trigger the add new appointment event).

Oct 19, 2009 at 9:24 PM

You need a timer because silverlight doesn't have a doubleclick event built in.

Please look at the Telerik Scheduler control out to get an idea what I thinking in terms of implementation. I still think their control isn't as good as microsoft's outlook scheduler control and it should be fairly easy to create something comparable.

http://demos.telerik.com/silverlight/#Scheduler/FirstLook

Oct 19, 2009 at 9:27 PM

Here some modification I would suggest on the visual side:

I did some research with both Outlook and a third party silverlight control to figure out what visual changes need to be made to function and look like the outlook version. I know these aren't vital changes to the functionality, but it should help with the visual design.

1. Set both the padding and border thickness of the scroll viewer control to zero.

2. Set the border thichness of 1,0,1,1 on each day content item.

3. Remove or hide the brd (border) object in the GetContent method of the ContentItemProvider class. I would stick with setting the borders of the individual day content items. On the current day, i would set the border of the day content item to 2 for left and right side.

4. Set the DaysOfWeek height to 19 in the ucCalendar template in the generics.xaml file

5. Set the width of the TimeSlots to 52 in generics.xaml file.

6. Set the margin of the week view to 52  in the populateheader method in the ucDaysofWeek class file.

 

Coordinator
Oct 19, 2009 at 9:47 PM

I really like the visual changes that you have suggested.  I have updated the files accordingly to your suggestions.  These will make it into the next release.

Oct 19, 2009 at 10:41 PM

That's good to hear. Everything I mentioned was researched from the outlook calendar control. The values I mentioned are absolute values. What did you think about the double click? I responded above.