Press "Enter" to skip to content

13 – MiniSqlAgent – Una classe per far comunicare Strati diversi della User Interface WPF

In questo post spieghiamo come fare in modo che uno User Control che si trova vari strati all’interno della user interface possa comunicare con la MainWindow dell’applicazione senza passare per l’ufficio complicazione affari semplici. Per farlo utilizzeremo i delegate e le Action.

Il problema

Nell’interfaccia della console del servizio MiniSqlAgent abbiamo iniziato ad implementare una User Interface complessa, che simula le Child Window di una MDI utilizzando il TabControl e gli user control. Gli User Control che gestiscono gli oggetti Job, possono trovarsi vari “strati” lontani dalla Window che li contiene, e non sapere nulla di tale window per il proprio funzionamento, ma sulla MainWindow abbiamo implementato una StatusBar, che ci mostra se il Servizio è attivo oppure no, e visto che abbiamo dello spazio, ci piacerebbe utilizzarla per dare dei messaggi di status all’utente. Come facciamo a fare arrivare alla MDI dei messaggi che arrivano dagli User Control senza complicarci troppo la vita?

La Soluzione

Usiamo un sistema simile a quello utilizzato per la gestione dell’EventLogger, solo che invece di utilizzare un Evento statico, utilizzeremo un semplice Delegate, per obbligarci ad utilizzare un solo metodo per eseguire il task. Vediamo come.

namespace Dnw.MiniSqlAgent.Console
{
    public static class StatusManager
    {
 
        private static Action<object, string> StatusChanged;
 
        public static void Notify(object sender, string message)
        {
            if (StatusChanged != null)
            {
                StatusChanged(sender, message);
            }
        }
 
        public static void Init(Action<object, string> handler)
        {
            StatusChanged = handler;
        }
    }
}

Implementiamo per prima cosa una classe statica che fornisce i servizi necessari. Per farlo definiamo una Action al suo interno, la classe generica Action è un metodo per definire dei delegate senza dover per forza creare nuovi oggetti delegate ad ogni necessità, la dichiarazione dell’action è equivalente a questa:

private static delegate void StatusChangedDelegate( object sender, string message);

Solamente è molto più compatta.

Il metodo Notify è quello che utilizzeremo per notificare alla UI una variazione di stato da pubblicare.

Il metodo Init ci permette di associare il metodo da eseguire quando una notifica viene inviata.

Vediamo come abbiamo aggiornato MainWindow per utilizzare la funzionalità:

public MainWindow()
{
    InitializeComponent();
    this.Icon = BitmapFrame.Create(new Uri("pack://application:,,,/msaIco.ico", UriKind.RelativeOrAbsolute));
    mWindowModel = new MainWindowModel();
    this.DataContext = mWindowModel;
    StatusManager.Init(JobsManagerStatusChanged);
}

private void JobsManagerStatusChanged(object sender, string message)
{
    mWindowModel.StatusMessage = message;
}

Nel costruttore della main window andiamo ad assegnare il delegate al manager, all’interno del delegate aggiorniamo la property che è in Binding al TextBlock.

<StackPanel 
    Grid.Column="1" 
    Orientation="Horizontal" 
    FlowDirection="LeftToRight">
    <TextBlock 
        VerticalAlignment="Center" 
        Text="{Binding StatusMessage}" 
        Style="{StaticResource Status}"/>
</StackPanel>

Lo Xaml che crea il textblock per il messaggio di status sulla barra della MainWindow.

public string StatusMessage
{
    get
    {
        return mStatusMessage;
    }
    set
    {
        mStatusMessage = value;
        OnPropertyChanged(FLD_StatusMessage);
    }
}

La property in binding definita nel view model della MainWindow.

void Job_Saved(object sender, RoutedEventArgs e)
{
    MiniSqlAgentJobControl jobC = sender as MiniSqlAgentJobControl;

    StatusManager.Notify(this, 
    string.Format(Properties.Resources.txtMSAJMJobSaved, jobC.JobFileName));
}

La chiamata all’interno dello User Control del JobManager che notifica il messaggio alla MainWindow senza la necessità di sapere nulla della MainWindow Stessa.

Il codice del progetto esempio collegato a questo articolo è disponibile al link seguente:

Il codice del progetto di esempio relativo alle nuove librerie comuni è disponibile al link seguente:

Per qualsiasi domanda, approfondimento, o curiosità, utilizzate pure il link alla form di contatto in cima alla pagina o il forum Microsoft Italia su cui rispondo regolarmente.