Per parlare dei data trigger penso sia utile fare un doppio salto mortale ! Infatti sono convinto che sia efficace mostrarne le funzionalità tramite l’ausilio di un controllo molto utilizzato in WPF, ListBox, e che sinora non abbiamo visto.

Questo ci permetterà di esporre in modo più agevole di questo tipo di trigger, oltre che iniziare a vedere un controllo abbastanza utilizzato nel mondo WPF.

Contestualmente a questo verranno esposti i rudimenti del databinding, che è il sistema tramite il quale è possibile connettere due proprietà di oggetti differenti e mantenerne i dati sincronizzati.

Del databinding ne parleremo diffusamente nel seguito, ma in questo post ne verrà mostrato un primo utilizzo pratico.

Ed ora... alcune parole su sua maestà ListBox !

Il ListBox è un controllo che permette di presentare una lista di item.

Occorre dire da subito che nel mondo WPF esistono vari controlli che permettono di ottenere medesimi risultati, ma questo in particolare si distingue per il fatto che è molto semplice da utilizzare e dispone inoltre di una funzionalità che permette anche di selezionare uno o più item.

Se siete pratici di programmazione anni '90 potete pensare questo controllo con un mix tra una griglia e una combo che permette la multiselezione.

 

 
  <Window x:Class="Wpf004_ListBox.MainWindow"
        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:local="clr-namespace:Wpf002_Trigger"
        mc:Ignorable="d"
        Title="MainWindow-ListBox" Height="350" Width="525">
    <Window.Resources>
    </Window.Resources>
        <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition />
        </Grid.RowDefinitions>
        <ListBox Grid.Row="0" Grid.Column="0" Name="ListaProvinceLiguri" SelectionMode="Multiple">
            <ListBoxItem>Imperia</ListBoxItem>
            <ListBoxItem>Savona</ListBoxItem>
            <ListBoxItem>Genova</ListBoxItem>
            <ListBoxItem>Spezia</ListBoxItem>
        </ListBox>
    </Grid>
</Window>

Dal codice sopra è possibile vedere un semplice esempio di utilizzo: la caratteristica di multiselezione cui si accennava prima è configurata nella proprietà SelectionMode.

Manco a dirlo nel code-behind è possibile accedere al controllo e variare la lista degli item presentati, utilizzando la proprietà Items.

public class Province
    {
        public string NomeProvincia {get;set;}
        public string SiglaProvincia {get;set;}

        public override string ToString()
        {
            return NomeProvincia + " ("+SiglaProvincia+")";
        }
    }

Quello sopra è l'oggetto che verrà rappresentato nella ListBox: la lista delle province della liguria. Qui nel seguito invece il relativo codice che trova posto nel code-behind.

public partial class MainWindow : Window
{
	public MainWindow()
	{
		InitializeComponent();
		ListaProvinceLiguri.Items.Add(new Province() {
			NomeProvincia = "Imperia",
			SiglaProvincia="IM"});
		ListaProvinceLiguri.Items.Add(new Province() {
			NomeProvincia = "Savona",
			SiglaProvincia = "SV"
		});
		ListaProvinceLiguri.Items.Add(new Province() {
			NomeProvincia = "Genova",
			SiglaProvincia = "GE"
		});
		ListaProvinceLiguri.Items.Add(new Province() {
			NomeProvincia = "Spezia",
			SiglaProvincia = "SP"
		});
		ListaProvinceLiguri.ItemsSource = mListaProvince;

	}
}

In modo sorprendente (?!) è anche possibile usare una List, da associare direttamente alla ListBox in binding.

public partial class MainWindow : Window
{
	public MainWindow()
	{
		InitializeComponent();
		ListaProvinceLiguri.Items.Add(new Province() {
			NomeProvincia = "Imperia",
			SiglaProvincia="IM"});
		ListaProvinceLiguri.Items.Add(new Province() {
			NomeProvincia = "Savona",
			SiglaProvincia = "SV"
		});
		ListaProvinceLiguri.Items.Add(new Province() {
			NomeProvincia = "Genova",
			SiglaProvincia = "GE"
		});
		ListaProvinceLiguri.Items.Add(new Province() {
			NomeProvincia = "Spezia",
			SiglaProvincia = "SP"
		});
		ListaProvinceLiguri.ItemsSource = mListaProvince;

	}
}

L’effetto finale di quanto sopra è assolutamente analogo al precedente: semplicemente si è creata una List di oggetti che quindi è stata assegnata alla ListBox: questo si occuperà quindi della sua visualizzazione.

Ora devo essere pedante e osservare un paio di cose: una volta associato un controllo ListBox a una lista di oggetti, è implicito che ogni elemento, ogni riga, di questo sia delegato a rappresentare un oggetto della lista stessa.

In modo originale ogni riga della ListBox è chiamato ListBoxItem: l'avessero chiamato Carletto forse sarebbe stato più divertente ma se ne sarebbe perso un pò in chiarezza, non trovate ?

Quindi detto ogni Carletto.... ooops, ogni ListBoxItem è associato a un oggetto della lista, ed è delegato alla sua rappresentazione.

Se non stabilito diversamente nel codice il framework rappresenterà l’oggetto in modo testuale, utilizzando quindi il relativo risultato del ToString.

Per questo motivo per avere una risultato sensato occorre implementare l’override del metodo ToString in modo da rappresentare il dato in modo corretto.

Vedremo più avanti come permettere al controllo di creare delle colonne che saranno delegate a contenere i dati in modo più strutturato e con rappresentazioni diverse dal semplice testo.

Ora si immagini di voler risolvere il problema di evidenziare una riga che contiene un determinato valore.

<Window x:Class="Wpf004_ListBox.MainWindow"
        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:local="clr-namespace:Wpf004_ListBox"
        mc:Ignorable="d"
        Title="ListBox-ConBindingEvoluto" Height="300" Width="300">
    <Grid >
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition />
        </Grid.RowDefinitions>
        <ListBox Grid.Row="0" Grid.Column="0" SelectionMode="Multiple" Name="ListaProvinceLiguri">
            <ListBox.ItemContainerStyle>
                <Style>  
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding Path=SiglaProvincia}" Value="IM">
                            <Setter Property="Control.Background" Value="Red"></Setter>
                        </DataTrigger>
                       
                    </Style.Triggers>
                </Style>
            </ListBox.ItemContainerStyle>  
        </ListBox>
    </Grid>
</Window>

Il codice espone la funzionalità per cui al verificarsi che Carletto.... ancora, scusate... cioè la ListBoxItem rappresenta la provincia con sigla IM allora predisponeil background rosso.

In pratica il DataTrigger agisce avendo come origine i dati: qui “tiene sott’occhio” il valore assunto dalla proprietà SiglaProvincia, che quando assume il valore previsto allora cambia lo stile.

Tutto questo per evidenziare IM, cioè la princia di Imperia, che è la mia provincia di nascita....... tutte le provincie sono importanti in modo uguale, ma qualcuna è più uguale delle altre...... e quindi è necessario evidenziarla in qualsiasi lista !