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:







martedì 23 agosto 2011

Silverlight 4.0 - WCF RIA Services - Enterprise Logging Application Block

SO Windows 7 a 64 bit - IIS 7.5 - VS2010 service pack1

Avevo questo tipo di problematica:

"Nella mia Silverlight Business Application ho implementato il Logging Application Block con l’estensione per Silverlight come da documentazione e tutto funziona correttamente, riesco a scrivere nel mio file di log tutte le informazioni che voglio, ma il fatto è che funziona solo se eseguo l’applicazione in emulazione, cioè con l’option “Usa Visual Studio Development Server”, se invece eseguo sempre da VS con “Usa server Web IIS Locale” l’applicazione non mi logga più niente. Credo sia un problema di permessi, però io ho dato i permessi alla cartella a tutto il mondo; ho cambiato anche l’identità di pool, impostandola a Nework Service, perché ho letto in un blog che WCF gira con Network Service, ma … niente da fare! E non so più dove sbattere la testa ... Naturalmente nell'event log di Windows non c'è nessun errore. A questo punto, qualsiasi altro suggerimento è bene accetto! Grazie mille!"

Alla fine ho trovato il motivo di tale anomalia.

Grazie Fiddler2!
Come capita spesso in questi casi, era una "baggianata"; in pratica era sbagliato l'endpoint del servizio WCF dell'applicazione Silverlight.
Era impostato nel seguente modo:

<endpoint address="/LoggingService.svc" ...

deve essere invece

<endpoint address="/MiaApplicazione.Web/LoggingService.svc" ...

Che sudata però ;-)

venerdì 19 agosto 2011

Silverlight - Close a ChildWindow

C# 4.0

Per chiudere una Child Window era stato impostato il seguente codice nell’evento di chiusura della view

private void WindowChild1_Close (object sender, MouseButtonEventArgs e)
        {
            DialogResult = true;
            Close();
        }
 
Questo però comportava che dopo un paio di chiusure della suddetta child l’intera applicazione era come fosse “disabilitata”, non si riusciva più ad interagire con il browser.

Ad oggi quindi per risolvere tale anomalia è stata aggiunta la seguente riga di codice:
 
Application.Current.RootVisual.SetValue(IsEnabledProperty, true);

L’evento è stato conseguentemente modificato nel seguente modo:

private void WindowChild1_Close (object sender, MouseButtonEventArgs e)
        {
            // Workaround to correctly close a child window
            Application.Current.RootVisual.SetValue(IsEnabledProperty, true);

            DialogResult = true;
            Close();
        }

… e così funziona!

martedì 9 agosto 2011

Silverlight 4.0 & IIS 7.5

Silverlight 4.0 (C#) & IIS 7.5

Pubblicando una Silverlight Business Application su IIS e richiamando la pagina di default dell’applicazione stessa http://localhost/BusinessApplication.Web/#/Home si ottiene il seguente messaggio d’errore: "Operazione Load non riuscita per la query 'GetUser'. Errore del server remoto: NotFound."



Il suddetto errore è stato risolto disabilitando l’autenticazione Windows su IIS.









martedì 2 agosto 2011

Web Services & SSL

C# 2.0 & IIS 7.5

Si vuole richiamare da un’applicazione client un metodo di un servizio web in modalità SSL (Secure Socket Layer) ed inoltre si vogliono nascondere i parametri del suddetto web method.
Si dà per assunto l’installazione del certificato nel server.

1.       Richiamare un metodo web in modalità SSL da un’applicazione client :

// Viene istanziato l’oggetto che si riferisce al web service
            DocumentHistory d = new DocumentHistory();
 
NetworkCredential networkCredential = new NetworkCredential("ciccio", "pasticcio");
       d.Credentials = networkCredential;

       ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };

       // Viene invocato il metodo richiesto
            object[] r = d.DepartmentReport("??", "??”, “!!”);

Da tenere presente quindi che se viene omessa la riga di codice evidenziata in giallo si verifica la seguente web exception:
 
“Connessione sottostante chiusa: Impossibile stabilire una relazione di trust per il canale sicuro SSL/TLS..”


2.  Per nascondere i parametri del metodo web si deve aggiungere il seguente elemento nel web.config del servizio web, all’interno dell’elemento <system.web>:

<system.web>
               <webServices>
              <protocols>
                <remove name="HttpPostLocalhost"/>
              </protocols>
            </webServices>
            </system.web>