in

DotNetSide

Dot Net South Italy Developers User Group

Articoli

Articoli pubblicati dagli iscritti a .netSide

Windows Form Skins: un controllo per cambiare la pelle ai tuoi windows forms con un click

di Leonardo Alario

Già da tempo, nel team di sviluppo dell’azienda per cui lavoro, stava “balenando” l’idea di costruire un controllo che gestisse, attraverso schemi xml, i controlli opportunamente mappati presenti sui form dei nostri applicativi.

Durante lo sviluppo di un progetto, i giorni uomo impiegati per progettare e sviluppare la GUI incide in modo notevole sulla durata del progetto stesso, sia per gestire la presentation, che per gestire l’aspetto funzionale di come la GUI deve interagire con il cliente stesso.

Ed ecco l’idea: mettere in piedi un meccanismo tale che tutti i controlli, sui nostri form, siano manipolabili dall’esterno, permettendoci magari di personalizzare l’applicativo dal cliente solo con qualche click, sia dal punto di vista grafico, che funzionale.

Così facendo, risparmieremmo preziosi giorni uomo sui nostri progetti, occupandoci di più della logica funzionale, rispetto alla presentazione dell’applicativo stesso.

Armato di Reflection e dell’interfaccia IExtenderProvider, mi sono messo a lavoro. 

 

Come funziona il controllo

Avevo già pensato a come il meccanismo di persistenza del controllo dovesse funzionare:

devo utilizzare un file xml per le skin contenente la mappatura di tutti i controlli presenti sul form e coadiuvato da un XmlSkinHelper che si occupa di caricare gli schemi in una lista di tipi generici.

Lo schema deve prendere in considerazione tutte le famiglie di controlli disponibili e, a parita di famiglia di controllo, consentire l’utilizzo di diverse impostazioni.

L’esempio seguente di skin file contiene la mappatura di diverse famiglie di controlli. Evidenzio che la famiglia ha due tipologie di mappatura:

  • La mappatura generica: riferita alla famiglia generica del controllo (es: <System.Windows.Forms.Button>)
  • La mappatura denominata: riferita ad un controllo particolare (es: <System.Windows.Forms.Button value="Prova">>

Ottenuto lo schema contenente la mappatura dei controlli, viene la parte difficile: come fare a processare le varie proprietà del controllo ?

Grazie alla reflection ed alla classe PropertyInfo Class (System.Reflection) il controllo incapsula tutta la logica per il caricamento delle proprietà dallo schema e per il relativo aggiornamento dei controlli presenti sul form selezionato.

 

Il controllo ai raggi X

Il controllo espone diverse proprietà e metodi, come elencato di seguito:

  • la proprietà string SkinFile: permette di leggere o settare il nome ed il percorso dello Skin File da applicare o applicato;

  • la proprietà bool AtLeastOneControlWasProcessed: indica se almeno una proprietà mappata nello schema, è stata processata con successo;

  • la proprietà string HowManyControlWasProcessed: indica il totale delle proprietà processate rispetto a quelle mappate nello schema;
  • Il metodo LoadSkinFile(): permette di ricaricare uno skin file già caricato in precedenza da disco; 
  • Il metodo LoadSkinFile(string SkinFile): permette di caricare il file di skin da disco;
  • Il metodo ApplySkin(): permette di applicare ai controlli del form le proprietà specificate nello schema caricato;

  • Il metodo ApplySkin(string SkinFile): permette di applicare ai controlli del form le proprietà specificate nello schema indicato;

Per utilizzare il controllo in un progetto è necessario aggiungere:

  1. un riferimento alla libreria WindowFormSkins.dll;
  2. aggiungiamo una direttiva Using: using SoftCantieri;
  3. aggiungiamo una nuova form che eredita da SoftCantieri.WindowFormSkin;

Invocando la form stessa avremo a disposizione i sopracitati metodi e proprietà.

Segue un piccolo esempio di utilizzo del controllo:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using SoftCantieri;

namespace DemoWindowsFormsSkins
{
public partial class FrmDemo : SoftCantieri.WindowFormSkin
{
private List<DummyBol> _ListaDummy = new List<DummyBol>();

public FrmDemo()
{
InitializeComponent();
}

private void Button1_Click(object sender, CancelEventArgs e)
{
try
{
// Carica il file xml skin selezionato
// e Memorizza lo skin in una collezione di oggetti
openFileDialog.Show();
this.SkinFile = openFileDialog.FileName;
this.LoadSkinFile(this.SkinFile);

// applica lo skin
this.ApplySkin();
TxtSkin.Text = this.SkinFile;
}
catch (Exception Ex)
{
MessageBox.Show("[" + Ex.Source + "]" + "\r" + Ex.Message, Application.ProductName,
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}

 

Il progetto allegato

Allegato all’articolo troverete un piccolo progetto demo che illustra il funzionamento del controllo. Per realizzarlo ho utilizzato i componenti Ascend.NET sia per testare lo spettro di controlli supportati sia per deliziare il palato sopraffino degli utenti sempre più affamati di interfacce accattivanti.

Se apriamo la soluzione o il progetto della demo allegato e selezioniamo in design mode un controllo presente sul form, otterremo la seguente situazione:

per ogni componente sul form verranno aggiunte, grazie all’interfaccia IextenderProvider e al provider di estensione implementato internamente nel controllo, le seguenti proprietà:

  • bool ControlStyleCanProcess: se impostata a true permette di processare il controllo selezionato, altrimenti in fase di elaborazione il controllo verrà ignorato;
  • String ControlStyle: a parita di famiglia di controllo permette di definirne il nome dello stile da applicare a patto che sia mappato nel file xml di skin con lo stesso nome;
  • Bool ControlStyleCanProcessOnEnterEvent: se impostato a true permette di processare il controllo quando riceve gli eventi del focus in entrata ed in uscita altrimenti, quando generati gli eventi del controllo verrano ignorati;
  • Color ControlOnEnterForeColor: permette di variare la proprietà forecolor del controllo, con il colore indicato, quando riceve il focus.
  • Color ControlOnEnterBackColor: permette di variare la proprietà Backcolor del controllo , con il colore indicato, quando riceve il focus.
  • Font ControlOnEnterFont: permette di variare il font del controllo , con il font indicato, quando riceve il focus.

Quando il controllo perde il focus ritornerà nello stato originario.

Ora apriamo il progetto della demo allegata, avviamolo, e selezioniamo lo skin file da applicare.

Nb. ho volutamente inserito uno skin con alcune proprietà mappate nel controllo in modo errato, quando lo aprirete riceverete un’eccezione con il nome della proprietà non valida:

quando selezioneremo lo skin file, i controlli nel form verranno processati e visualizzati con i nuovi valori indicati nello skin file.

Tutti gli skin file xml, non formattati secondo le specifiche suddette, non verrano presi in considerazione dal controllo; in sostanza il controllo non cambierà aspetto, così come in presenza di nomi o di valori delle proprietà errati, in un file di skin aderente alle specifiche,verranno segnalate all’utente con delle eccezioni.

 

Conclusioni

Per eventuali segnalazioni di anomalie o chiarimenti sul controllo in questione potete scrivere a questo indirizzo leo.alario.software@email.it .

Sono previste nuove implementazioni ed estensioni per il controllo:

  • la possibilità di aggiungere il controllo al form in modo visuale; senza, che il form stesso erediti dal controllo;
  • la possibilità di generare gli schemi xml selezionando il form sorgente, in modo da automatizzare la creazione degli schemi contenenti i controlli posizionati sul form selezionato;
  • il monitoraggio dello skin file selezionato, per verificare se sono intervenute variazioni ed eventualmente ricaricarlo;
  • un meccanismo di RollBack allo stato precedente dei controlli già processati, quando si presenta un eccezione durante l’elaborazione;

Chiunque vorrà, potrà implementare le funzionalità sopraindicate e segnalarmi le eventuali modifiche al codice in allegato.

Spero che questo piccolo componente possa ritornare utile a qualcuno facendogli risparmiare preziosi giorni uomo, spada di Damocle sulle teste di noi “poveri” tartassati programmatori.

Note

Come detto in precedenza, nel progetto sono stati utilizzati gli Ascend.Net controls.Il progetto contiene nella cartella \..\Bin gli assembly per far funzionare correttamente la demo.

Chiunque fosse interessato può scaricare i controlli o avere maggiori informazioni sugli stessi al seguente link: http://www.codeplex.com/Tagging/TagDetail.aspx?TagName=Ascent.Net

Only published comments... Apr 02 2007, 01:00 AM by DotNetSide Staff
Filed under: ,
Powered by Community Server (Commercial Edition), by Telligent Systems