mercoledì 24 agosto 2011

Silverlight - Tooltip su dei giorni particolari di un controllo Calendar

Silverlight 4.0

L’esigenza è quella ottenere un tooltip su alcuni giorni particolari, evidenziati in rosso, di un oggetto Calendar, ad esempio per evidenziare le proprie scadenze fiscali; e questa è la soluzione che ho adottato.
Come prima cosa ho creato i seguenti converter, uno per i giorni in “rosso” e l’altro per il tooltip:

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Windows.Data;
using System.Windows.Media;

namespace ContabilitaSelfService.Converter
{
    public class BackgroundDayCalendarConverter : IValueConverter
    {
        //public static IList<DateTime> Holidays { get; set; }
        public static IList<DateTime> Evidences { get; set; }

        public object Convert(object value,
                            Type targetType,
                            object parameter,
                            CultureInfo culture)
        {
            DateTime date = (DateTime)value;

            if (Evidences != null && Evidences.Contains(date))
                return new SolidColorBrush(Colors.Red);
            else if (date.Date == DateTime.Now.Date)
                return new SolidColorBrush(Colors.LightGray);
            else
                return new SolidColorBrush(Colors.Transparent);
        }

        public object ConvertBack(object value, Type targetType,
        object parameter, CultureInfo culture)
        {
            return null;
        }
    }
}


using System;
using System.Collections.Generic;
using System.Globalization;
using System.Windows.Data;

namespace ContabilitaSelfService.Converter
{
    public class TooltipDayCalendarConverter : IValueConverter
    {
        public static IDictionary<DateTime, string> Tooltips { get; set; }

        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            DateTime date = (DateTime)value;

            if (Tooltips != null && Tooltips.ContainsKey(date))
                return Tooltips[date];

            return null;
        }


        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return null;
        }
    }
}

Ho creato poi in un’ottica di riusabilità il seguente user control
<UserControl x:Class="ContabilitaSelfService.UserControls.DeskTop"

    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:prim="clr-namespace:System.Windows.Controls.Primitives;assembly=System.Windows.Controls"

    xmlns:src="clr-namespace:ContabilitaSelfService.Converter" xmlns:sdk="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls" mc:Ignorable="d"

    d:DesignHeight="500" d:DesignWidth="180">

    <UserControl.Resources>

        <src:BackgroundDayCalendarConverter x:Key="BackgroundDayCalendarConverter" />

        <src:TooltipDayCalendarConverter x:Key="TooltipDayCalendarConverter" />

        <Style x:Key="CalendarDayButtonStyle1" TargetType="prim:CalendarDayButton">

            <Setter Property="Template">

                <Setter.Value>

                    <ControlTemplate TargetType="prim:CalendarDayButton">

                        <Grid Background="{Binding Converter={StaticResource BackgroundDayCalendarConverter}, Path=Date}"

                              ToolTipService.ToolTip="{Binding Converter={StaticResource TooltipDayCalendarConverter}, Path=Date}">

                            <ContentControl x:Name="Content" Margin="5,1,5,1" Content="{TemplateBinding Content}" />

                        </Grid>

                    </ControlTemplate>

                </Setter.Value>

            </Setter>

        </Style>

    </UserControl.Resources>

    <Grid x:Name="LayoutRoot" Background="White">
        <sdk:Calendar HorizontalAlignment="Right" CalendarDayButtonStyle="{StaticResource CalendarDayButtonStyle1}" >
        </sdk:Calendar>
    </Grid>
</UserControl>

Da notare la parte di binding relativa ai converter.
A questo punto ho caricato le collection interne Evidences e Tooltips prendendo le informazioni da una tabella, nella quale sono state memorizzate tutte le mie scadenze. Tralasciando la parte di recupero dei dati, questa è la procedura per il caricamento delle scadenze:

private void LoadScadenzeCallBack(LoadOperation<Scadenzario> obj)
        {
            BackgroundDayCalendarConverter.Evidences = new List<DateTime>();
            TooltipDayCalendarConverter.Tooltips = new Dictionary<DateTime, string>();

            foreach (var scadenza in _context.Scadenzarios)
            {
                BackgroundDayCalendarConverter.Evidences.Add(scadenza.DataScadenza);
                TooltipDayCalendarConverter.Tooltips.Add(scadenza.DataScadenza, scadenza.Descrizione);  
            }           
        }

Nel mio caso, questo è il risultato finale: