This article is currently in the process of being translated into Italian (~99% done).
The ComboBox control
Il controllo ComboBox è in molti modi simile al controllo ListBox, ma occupa molto meno spazio, poiché l'elenco degli elementi è nascosto quando non necessario. Il controllo ComboBox viene utilizzato in molti punti di Windows, ma per assicurarci che tutti sappiano come appare e funziona, passeremo direttamente a un semplice esempio:
<Window x:Class="WpfTutorialSamples.ComboBox_control.ComboBoxSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ComboBoxSample" Height="150" Width="200">
<StackPanel Margin="10">
<ComboBox>
<ComboBoxItem>ComboBox Item #1</ComboBoxItem>
<ComboBoxItem IsSelected="True">ComboBox Item #2</ComboBoxItem>
<ComboBoxItem>ComboBox Item #3</ComboBoxItem>
</ComboBox>
</StackPanel>
</Window>
Nello screenshot, ho attivato il controllo facendo clic su di esso, causando la visualizzazione dell'elenco di elementi. Come puoi vedere dal codice, ComboBox, nella sua forma semplice, è molto facile da usare. Tutto quello che ho fatto qui è aggiungere manualmente alcuni elementi, rendendone uno selezionato per impostazione predefinita impostando la proprietà IsSelected su di esso.
Contenuto Custom
Nel primo esempio abbiamo mostrato solo il testo negli elementi, il che è abbastanza comune per il controllo ComboBox, ma poiché ComboBoxItem è un ContentControl, possiamo effettivamente usare praticamente qualsiasi cosa come contenuto. Proviamo a fare un elenco leggermente più sofisticato di elementi:
<Window x:Class="WpfTutorialSamples.ComboBox_control.ComboBoxCustomContentSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ComboBoxCustomContentSample" Height="150" Width="200">
<StackPanel Margin="10">
<ComboBox>
<ComboBoxItem>
<StackPanel Orientation="Horizontal">
<Image Source="/WpfTutorialSamples;component/Images/bullet_red.png" />
<TextBlock Foreground="Red">Red</TextBlock>
</StackPanel>
</ComboBoxItem>
<ComboBoxItem>
<StackPanel Orientation="Horizontal">
<Image Source="/WpfTutorialSamples;component/Images/bullet_green.png" />
<TextBlock Foreground="Green">Green</TextBlock>
</StackPanel>
</ComboBoxItem>
<ComboBoxItem>
<StackPanel Orientation="Horizontal">
<Image Source="/WpfTutorialSamples;component/Images/bullet_blue.png" />
<TextBlock Foreground="Blue">Blue</TextBlock>
</StackPanel>
</ComboBoxItem>
</ComboBox>
</StackPanel>
</Window>
Per ciascuno dei ComboBoxItem ora aggiungiamo uno StackPanel, in cui aggiungiamo un'immagine e un blocco di testo. Questo ci dà il pieno controllo del contenuto e del rendering del testo, come puoi vedere dallo screenshot, dove sia il colore del testo che l'immagine indicano un valore di colore.
Data binding in un ComboBox
Come puoi vedere dai primi esempi, definire manualmente gli elementi di un controllo ComboBox è facile usando XAML, ma probabilmente ti imbatterai presto in una situazione in cui hai bisogno che gli elementi provengano da un qualche tipo di origine dati, come un database o semplicemente un elenco in memoria. Utilizzando l'associazione dati WPF e un modello personalizzato, possiamo facilmente visualizzare un elenco di colori, inclusa un'anteprima del colore:
<Window x:Class="WpfTutorialSamples.ComboBox_control.ComboBoxDataBindingSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ComboBoxDataBindingSample" Height="200" Width="200">
<StackPanel Margin="10">
<ComboBox Name="cmbColors">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Rectangle Fill="{Binding Name}" Width="16" Height="16" Margin="0,2,5,2" />
<TextBlock Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
</Window>
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media;
namespace WpfTutorialSamples.ComboBox_control
{
public partial class ComboBoxDataBindingSample : Window
{
public ComboBoxDataBindingSample()
{
InitializeComponent();
cmbColors.ItemsSource = typeof(Colors).GetProperties();
}
}
}
In realtà è abbastanza semplice: nel Code-behind, ottengo un elenco di tutti i colori usando un approccio basato su Reflection con la classe Colors. Lo assegno alla proprietà ItemsSource di ComboBox, che quindi esegue il rendering di ogni colore utilizzando il modello che ho definito nella parte XAML.
Ogni item, come definito da ItemTemplate, è costituito da StackPanel con un rettangolo e un blocco di testo, ciascuno associato al valore del colore. Questo ci dà un elenco completo di colori.
Proprietà IsEditable
Nei primi esempi, l'utente è aveva solamente la possibilità di selezionare dall'elenco di elementi, ma una delle cose interessanti di ComboBox è anche consentire all'utente di immettere il proprio valore. Ciò è estremamente utile nelle situazioni in cui si desidera aiutare l'utente fornendogli un set predefinito di opzioni, pur offrendo l'opzione di inserire manualmente il valore desiderato. Tutto questo è controllato dalla proprietà IsEditable, che trasforma un po' il comportamento e l'aspetto del ComboBox:
<Window x:Class="WpfTutorialSamples.ComboBox_control.ComboBoxEditableSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ComboBoxEditableSample" Height="150" Width="200">
<StackPanel Margin="10">
<ComboBox IsEditable="True">
<ComboBoxItem>ComboBox Item #1</ComboBoxItem>
<ComboBoxItem>ComboBox Item #2</ComboBoxItem>
<ComboBoxItem>ComboBox Item #3</ComboBoxItem>
</ComboBox>
</StackPanel>
</Window>
Come puoi vedere, posso inserire un valore completamente diverso o selezionarne uno dall'elenco. Se selezionato dall'elenco, sovrascrive semplicemente il testo di ComboBox.
Come piccolo bonus, il ComboBox cercherà automaticamente di aiutare l'utente a selezionare un valore esistente quando l'utente inizia a digitare, come puoi vedere dal prossimo screenshot, dove ho iniziato a digitare "Co":
Per impostazione predefinita, la corrispondenza non fa distinzione tra maiuscole e minuscole, ma puoi farlo impostando IsTextSearchCaseSensitive su True. Se non vuoi questo comportamento di completamento automatico, puoi disabilitarlo impostando IsTextSearchEnabled su False.
Lavorare con la selezione di ComboBox
Una parte fondamentale dell'utilizzo del controllo ComboBox è quella di poter leggere la selezione dell'utente e persino controllarla con il codice. Nel prossimo esempio ho riutilizzato il file esempio ComboBox associato a dati, ma ho aggiunto alcuni pulsanti per il controllo della selezione. Ho anche usato l'evento SelectionChanged per capire quando l'elemento selezionato viene modificato, tramite codice o dall'utente.
Di seguito l'esempio:
<Window x:Class="WpfTutorialSamples.ComboBox_control.ComboBoxSelectionSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ComboBoxSelectionSample" Height="125" Width="250">
<StackPanel Margin="10">
<ComboBox Name="cmbColors" SelectionChanged="cmbColors_SelectionChanged">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Rectangle Fill="{Binding Name}" Width="16" Height="16" Margin="0,2,5,2" />
<TextBlock Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<WrapPanel Margin="15" HorizontalAlignment="Center">
<Button Name="btnPrevious" Click="btnPrevious_Click" Width="55">Previous</Button>
<Button Name="btnNext" Click="btnNext_Click" Margin="5,0" Width="55">Next</Button>
<Button Name="btnBlue" Click="btnBlue_Click" Width="55">Blue</Button>
</WrapPanel>
</StackPanel>
</Window>
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Windows;
using System.Windows.Media;
namespace WpfTutorialSamples.ComboBox_control
{
public partial class ComboBoxSelectionSample : Window
{
public ComboBoxSelectionSample()
{
InitializeComponent();
cmbColors.ItemsSource = typeof(Colors).GetProperties();
}
private void btnPrevious_Click(object sender, RoutedEventArgs e)
{
if(cmbColors.SelectedIndex > 0)
cmbColors.SelectedIndex = cmbColors.SelectedIndex - 1;
}
private void btnNext_Click(object sender, RoutedEventArgs e)
{
if(cmbColors.SelectedIndex < cmbColors.Items.Count-1)
cmbColors.SelectedIndex = cmbColors.SelectedIndex + 1;
}
private void btnBlue_Click(object sender, RoutedEventArgs e)
{
cmbColors.SelectedItem = typeof(Colors).GetProperty("Blue");
}
private void cmbColors_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
Color selectedColor = (Color)(cmbColors.SelectedItem as PropertyInfo).GetValue(null, null);
this.Background = new SolidColorBrush(selectedColor);
}
}
}
La parte interessante di questo esempio sono i tre gestori di eventi per i nostri tre pulsanti, nonché il gestore di eventi SelectionChanged . Nei primi due, selezioniamo l'elemento precedente o successivo leggendo la proprietà SelectedIndex e quindi sottraendo o aggiungendone uno.
Nel gestore del terzo evento, utilizziamo SelectedItem per selezionare un elemento specifico in base al valore. Qui uso .NET reflection: ComboBox è associato a un elenco di proprietà, ciascuna delle quali è un colore, anziché un semplice elenco di colori; fondamentalmente si tratta di dare il valore contenuto da uno degli elementi nella proprietà SelectedItem .
Nel gestore dell'ultimo e quarto evento, rispondo alla modifica dell'elemento selezionato. Quando ciò accade, leggo il colore selezionato (ancora una volta usando Reflection, come descritto sopra) e quindi utilizzare il colore selezionato per creare un nuovo pennello di sfondo per la Finestra. L'effetto può essere visto nello screenshot.
Se stai lavorando con un ComboBox modificabile (proprietà IsEditable impostata su true), puoi leggere la proprietà Text per conoscere il valore dell'utente entrato o selezionato.