Version

Custom Color Scheme

Overview

XamScheduleDataManager, which is associated with the view controls through their DataManager property, exposes a property named ColorScheme which can be set to an instance of a class derived from CalendarColorScheme. This class exposes a set of base colors that each get assigned to individual ResourceCalendars. It also has a virtual method for returning a brush for a specific base color for a specific usage, identified by the CalendarBrushId enum, e.g., AppointmentBackground, WeekHeaderBorder, etc.

If you want to supply a completely custom color scheme you can derive a class from CalendarColorScheme and provide logic to supply every brush for every CalendarBrushId value. However, you can also derive it from one of the supplied classes, e.g., Office2010ColorScheme, and provide custom brushes for just a few CalendarBrushIds.

CalendarColorScheme Properties

  • BaseColors – this returns a read-only collection of colors that the scheme supports. This must return at least one color.

  • DefaultBaseColor – this returns the base color to use for brushes on elements that don’t have a ResourceCalendar context. The base implementation returns the first color in the BaseColors collection.

  • DialogResources – this returns a ResourceDictionary that will get inserted into each dialog’s resources. This allows a derived class to provide custom resources that will get picked up by the dialogs. Note: normally this property is not overridden. Instead the virtual CreateDialogResources and VerifyDialogResources methods are overridden (see below).

  • ScrollBarStyle – this returns a style for scrollbars. The default implementation returns null.

CalendarColorScheme Methods

  • CreateBrush – this is passed a CalendarBrushId and a base color. It must return a brush. For efficiency in WPF the brush should be frozen. Note: it is possible that the base color passed into this method is not included in the BaseColors collection. This can happen if the BaseColor property of a ResourceCalendar is set to a color that is not in the collection.

  • CreateDialogResources – this is overridden to lazily create the resources needed for the dialogs the first time the DialogResources property is accessed.

  • OnSystemColorsChanged – can be overridden to detect when the system colors have changed. Note that this will only get called in WPF. In Silverlight there is no notification when the system colors change.

  • VerifyDialogResources – this method is called every time the DialogResources property is accessed, e.g., before a dialog is displayed. This gives derived classes an opportunity to update the resources before each dialog is shown.

How do elements access Color Scheme brushes?

Accessing the color scheme’s brushes is done through the CalendarBrushProvider class. This class represents a base color and exposes an indexer that takes a CalendarBrushId. The indexer checks its cached brushes and if the id is not found it will call the CalendarColorScheme’s CreateBrush method and cache the value before returning it.

Note: call the CalendarColorScheme’s InvalidateBrushCache method to clear the cached brushes for the CalendarBrushProviders associated with all base colors.

For example:

In Visual Basic:

Me.dayView1.DataManager.ColorSchemeResolved.InvalidateBrushCache()

In C#:

this.dayView1.DataManager.ColorSchemeResolved.InvalidateBrushCache();

Elements will locate an appropriate CalendarBrushProvider in one of following ways:

  1. For elements that have a ResourceCalendar context, they can access the ResourceCalendar’s read-only BrushProvider property and then use the indexer to access a specific brush. If the ResourceCalendar’s BaseColor property is not null then that will determine which CalendarBrushProvider is returned by the BrushProvider property. Otherwise, brush providers are assigned so that each ResourceCalendar has a different base color if possible. If there are more visible ResourceCalendars than there are base colors then the providers are allocated to try to minimize base color re-use.

  2. For elements that are not related to a specific ResourceCalendar that have a ScheduleControlBase context, they can access the default brush provider by binding to the control’s DataManager. ColorSchemeResolved. DefaultBrushProvider property.

  3. There is also an attached BrushProvider property on CalendarBrushProvider that can be set on any element.

Note: many of the elements (e.g., ActivityPresenter, CalendarHeader, etc.) access the CalendarBrushProvider in code and then expose read-only "Computed…​" properties that are used for binding by elements in their templates.

Examples:

The following example just returns a new set of base colors:

In Visual Basic:

Public Class NewColorScheme1
    Inherits Office2010ColorScheme
    Public Overrides ReadOnly Property BaseColors() As
        ReadOnlyCollection(Of Color)
        Get
            Return New ReadOnlyCollection(Of Color)(_
                New Color() {Colors.Red, Colors.Yellow, Colors.Blue})
        End Get
    End Property
End Class

In C#:

public class NewColorScheme1 : Office2010ColorScheme
{
    public override ReadOnlyCollection<Color> BaseColors
    {
        get
        {
            return new ReadOnlyCollection<Color>(
                new Color[] { Colors.Red, Colors.Yellow, Colors.Blue }
            );
        }
    }
}

The next example just returns a brush for a single id:

In Visual Basic:

Public Class NewColorScheme2
    Inherits Office2010ColorScheme
    Protected Overrides Function CreateBrush(id As
        CalendarBrushId, baseColor As Color) As Brush
        Dim color__1 As Color
        Select Case id
            Case CalendarBrushId.AppointmentBackground
                If Me.IsHighContrast Then
                    ' when the OS has a high-contrast theme it is best
                    ' to use one of the SystemColors.
                    ' Note: when the OS theme is changed the cache
                    ' is automatically cleared so that this method can
                    ' get called again
                    color__1 = SystemColors.WindowColor
                Else
                    ' if a hard-coded color is specified here every
                    ' provider will get the same brush regardless
                    ' of its base color.
                    ' Another option is to write code to return a
                    ' color based on the passed in baseColor by e.g.
                    ' manipulating its luminosity and/or saturation or
                    ' by some other algorithm.
                    color__1 = Color.FromArgb(255, 123, 122, 57)
                End If
                Exit Select
            Case Else
                Return MyBase.CreateBrush(id, baseColor)
        End Select
        Dim br As Brush = New SolidColorBrush(color__1)
        #If Not SILVERLIGHT Then
        br.Freeze()
        #End If
        Return br
    End Function
End Class

In C#:

public class NewColorScheme2 : Office2010ColorScheme
{
    protected override Brush CreateBrush(CalendarBrushId id,
        Color baseColor)
    {
        Color color;
        switch (id)
        {
            case CalendarBrushId.AppointmentBackground:
            if (this.IsHighContrast)
            {
                // when the OS has a high-contrast theme it is best
                // to use one of the SystemColors.
                // Note: when the OS theme is changed the cache
                // is automatically cleared so that this method can
                // get called again
                color = SystemColors.WindowColor;
            }
            else
            {
                // if a hard-coded color is specified here every
                // provider will get the same brush regardless
                // of its base color.
                // Another option is to write code to return a
                // color based on the passed in baseColor by e.g.
                // manipulating its luminosity and/or saturation or
                // by some other algorithm.
                color = Color.FromArgb(255, 123, 122, 57);
            }
            break;
            default:
            return base.CreateBrush(id, baseColor);
        }
        Brush br = new SolidColorBrush(color);
        #if !SILVERLIGHT
        br.Freeze();
        #endif
        return br;
    }
}