WPF Style in external assembly

Gestendo un progetto WPF abbastanza complesso, mi sono scontrato con la necessita’ di avere una serie di Style e Template globali per tutti gli elementi grafici della mia applicazione, da centralizzare in un unico assembly e da referenziare poi nei vari progetti che compongono la mia soluzione.

Ho risolto usando dei ResourceDictionary dove immagazzinare queste risorse e usando delle Pack URI per referenziare questi dizionari nei vari progetti.

Qualche info su come spostare uno style dal singolo elemento fino ad un livello condiviso da tutta l’applicazione (il ResourceDictionary): Styles in WPF (2) – Styles, Resources and ResourceDictionaries.

Per avere un’idea un po’ piu’ approfondita sulle Pack URI: Pack URIs in Windows Presentation Foundation.

 

CREARE L’ASSEMBLY CON LE RISORSE CONDIVISE

Dato che nell’assembly andranno a finire alcuni controlli WPF personalizzati, ho aggiunto alla soluzione corrente un nuovo progetto di tipo WPF Custom Control Library, chiamandolo MyTestProject.WPF.Global.

Ho poi creato una cartella Styles (nome arbitrario) e all’interno di questa cartella ho aggiunto un nuovo item di tipo Resource Dictionary (WPF), con nome GlobalStyles.xaml. In questo file xaml ho caricato i miei stili globali, ad esempio aggiungendo qualcosa tipo:


<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <Style x:Key="CellTextStyle">
        <Setter Property="TextElement.FontSize" Value="12" />
        <Setter Property="TextElement.FontWeight" Value="Bold" />
    </Style>
</ResourceDictionary>

Ora, se voglio usare questo stile all’interno di un controllo personalizzato nello stesso progetto, occorre prima richiamarlo nel file xaml del controllo (appena sotto il tag UserControl):

<!– Usa il file di ResourceDictionary con gli stili globali –>
<UserControl.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="Styles\GlobalStyles.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</UserControl.Resources>

(occhio che nomecartella\nomefile.xaml siano corretti) e poi usarlo a seconda delle esigenze:

<Label
    Name="label1"
    Style="{StaticResource CellTextStyle}">
    LabelLabelLabelLabelLabel
</Label>

 

IMPOSTARE LO STILE NEL PROGETTO PRINCIPALE

Come prima cosa occorre aggiungere alle refence del progetto il progetto contenente gli stili condivisi.

Poi, nel file App.xaml bisogna richiamare questo stile aggiungendolo ai resource dictionary dell’applicazione.

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="pack://application:,,,/MyTestApp.WPF.Common;component/Styles/GlobalStyles.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
    …..
</Application.Resources>
       
(oltre che prestare attenzione a nomecartella\nomefile.xaml, stavolta c’e’ di mezzo anche il nome dell’assembly dove risiedono). Stessa sintassi mostrata sopra per usare lo stile all’interno dei file xaml dell’applicazione.

Ovviamente se non si vuole condividere lo stile tra tutti gli elementi del progetto, basta spostare questa dichiarazione nel blocco Page.Resources o Window.Resources a seconda del file xaml dove si intende usare lo stile, togliendola dall’App.xaml.


 

CONSIDERAZIONI AGGIUNTIVE

Utilizzando la proprieta’ TargetType e togliendo quella x:Key dell’elemento Style e’ possibile creare uno stile che viene automaticamente applicato a tutti gli elementi del tipo definito in TargetType. Specificando, ad esempio, "Button", tutti i bottoni presenti in file xaml dove lo stile agisce saranno influenzati. Con questo approccio si puo’ facilmente creare una personalizzazione grafica da usare in tutte le applicazioni, mantenendo con facilita’ una coerenza visiva nello sviluppo.

La proprieta’ BasedOn dell’elemento Style offre la possibilita’ di definire uno stile appoggiandosi su uno gia’ esistente. Quindi magari si puo’ definire uno stile globale e poi fare piccole personalizzazioni a seconda delle esigenze. Oppure stili globali in cascata, da applicare a secondo dei casi.

Putting resource in separate xaml files descrive come impostare uno stile globale, ma via codice C# invece che direttamente nei file xaml. Utile se occorre incudee qualche logica di scelta per decidere lo stile da caricare.

Leave a Reply