This article has been localized into Czech by the community.
Ovládací prvek ComboBox
Ovládací prvek ComboBox je v mnoha ohledech podobný ovládacímu prvku ListBox, ale zabírá mnohem méně místa, protože seznam položek je skryt, když není potřeba. Ovládací prvek ComboBox se používá na mnoha místech ve Windows, ale abychom se ujistili, že všichni vědí, jak vypadá a jak funguje, přejdeme rovnou k jednoduchému příkladu:
<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>
Na snímku jsem aktivoval ovládací prvek kliknutím na něj, čímž se zobrazil seznam položek. Jak můžete vidět z kódu, ComboBox je ve své jednoduché formě velmi snadno použitelný. Vše, co jsem zde udělal, je manuální přidání několika položek a nastavení jedné z nich jako výchozí, pomocí vlastnosti IsSelected.
Vlastní obsah
V prvním příkladu jsme v položkách zobrazovali pouze text, což je pro ovládací prvek ComboBox poměrně běžné, ale protože ComboBoxItem je ovládací prvek obsahu (ContentControl), můžeme vlastně použít téměř cokoli jako obsah. Pojďme vyzkoušet vytvořit trochu sofistikovanější seznam položek:
<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>
Pro každou z položek ComboBoxItem nyní přidáme StackPanel, do kterého vložíme obrázek a TextBlock. To nám dává plnou kontrolu nad obsahem, stejně jako nad vykreslováním textu, jak vidíte na snímku, kde barva textu, tak obrázek indikují hodnotu barvy.
Vázání dat (data binding) ke ComboBoxu
Jak můžete vidět z prvních příkladů, manuální definování položek ovládacího prvku ComboBox je snadné pomocí XAML, ale pravděpodobně se brzy setkáte se situací, kdy potřebujete, aby položky pocházely z nějakého datového zdroje, jako je databáze nebo jen seznam v paměti. Použitím datové vazby WPF (data bindingu) a vlastní šablony, můžeme snadno vykreslit seznam barev, včetně náhledu barvy:
<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();
}
}
}
Je to vlastně docela jednoduché: V Code-behind získám seznam všech barev pomocí přístupu založeného na reflexi s třídou Colors. Přiřadím ji k vlastnosti ItemsSource ComboBoxu, který pak vykreslí každou barvu pomocí šablony, kterou jsem definoval v části XAML.
Každá položka, jak je definována v ItemTemplate, se skládá ze StackPanelu s obdélníkem (Rectangle) a TextBlockem, které jsou oba vázány na hodnotu barvy. To nám poskytuje úplný seznam barev s minimálním úsilím - a vypadá to docela dobře, že ano?
Vlastnost IsEditable (je editovatelný)
V prvních příkladech byl uživatel schopen vybírat pouze z našeho seznamu položek, ale jedna z vychytávek ovládacího prvku ComboBox je, že podporuje možnost umožnit uživateli jak výběr ze seznamu položek, tak i zadání vlastní hodnoty. To je extrémně užitečné v situacích, kde chcete uživateli pomoci tím, že mu dáte předdefinovaný soubor možností, ale zároveň mu dáte možnost ručně zadat požadovanou hodnotu. Toto vše je ovládáno vlastností IsEditable, která docela výrazně mění chování a vzhled ComboBoxu:
<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>
Jak můžete vidět, mohu zadat úplně jinou hodnotu nebo vybrat jednu z nabízených možností. Pokud je vybrána možnost ze seznamu, tak jednoduše přepíše text ComboBoxu.
Jako pěkný malý bonus se ComboBox automaticky pokusí pomoci uživateli vybrat existující hodnotu, když uživatel začne psát text, jak můžete vidět na dalším snímku, kde jsem začal psát "Co":
Ve výchozím nastavení není vyhledávání citlivé na velká a malá písmena, ale můžete tuto case-sensitive citlivost zapnout tím, že nastavíte vlastnost IsTextSearchCaseSensitive na True. Pokud tuto funkci automatického doplňování vůbec nechcete, můžete ji zakázat tím, že nastavíte IsTextSearchEnabled na False.
Práce s výběrem v prvku ComboBox
Klíčovou částí použití ovládacího prvku ComboBox je schopnost čtení výběru uživatele a dokonce jeho ovládání pomocí kódu. V následujícím příkladu jsem znovu použil ovládací prvek ComboBox s datovou vazbou (data binding), ale přidal jsem několik tlačítek pro ovládání výběru. Také jsem využil událost SelectionChanged k zachycení změny vybrané položky, ať už kódem nebo uživatelem, a reagovat na ni.
Zde je příklad:
<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);
}
}
}
Zajímavou částí tohoto příkladu jsou tři obsluhy událostí pro naše tři tlačítka, stejně jako obsluha události SelectionChanged. V prvních dvou případech vybereme předchozí nebo následující položku tím, že přečteme vlastnost SelectedIndex a následně od ní odečteme nebo přičteme jedničku. Docela jednoduché a snadno ovladatelné.
V třetí obsluze události používáme SelectedItem k výběru konkrétní položky na základě hodnoty. Dělám tu trochu práce navíc (pomocí .NET reflexe), protože ComboBox je vázán na seznam vlastností, přičemž každá z nich je barva, namísto jednoduchého seznamu barev, ale v podstatě jde o to, přiřadit hodnotu obsaženou v jedné z položek vlastnosti SelectedItem.
Ve čtvrté a poslední obsluze události reaguji na změnu vybrané položky. Když k tomu dojde, přečtu vybranou barvu (znovu pomocí reflexe, jak je popsáno výše) a poté použiji vybranou barvu k vytvoření nového pozadí pro okno. Efekt můžete vidět na snímku.
Pokud pracujete s editovatelným ComboBoxem (vlastnost IsEditable je nastavena na true), můžete číst vlastnost Text, abyste zjistili hodnotu, kterou uživatel zadal nebo vybral.