TOC

This article has been localized into German by the community.

Listen-Steuerelemente:

Die ComboBox

Das ComboBox Kontrollelement verhält sich in vielerlei Hinsicht wie ein ListBox Kontrollelement, jedoch mit dem Unterschied, dass die angezeigten Elemente versteckt werden, wenn sie nicht gebraucht werden. Dadurch nimmt das Kontrollelement weniger Platz ein. Das ComboBox Kontrollelement findet innerhalb von Windows viele Anwendungsfälle, aber um sicherzugehen, dass jeder weiß wie es aussieht und wie es funktioniert zeigen wir gleich ein Beispiel.

<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>

In dem Screenshot wurde das Kontrollelement durch anklicken aktiviert. Dadurch wird die Liste der Elemente sichtbar. Wie in dem Code-Beispiel zu erkennen ist, ist die ComboBox in seiner einfachsten Form sehr leicht zu benutzen. Alles was gemacht wurde ist einige Elemente per Hand hinzuzufügen und das Standardelement durch die IsSelected Eigenschaft zu markieren.

Modifizierte Inhalte

Im ersten Beispiel haben wir nur Text angezeigt, was für die ComboBox der Normalfall ist. Da das ComboBoxItem jedoch eine ContentControl ist können wir so ziemlich alles als Inhalt anzeigen lassen. Das versuchen wir indem wir eine etwas anspruchsvollere Liste an Inhalten anzeigen.

<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>

Für jedes ComboBoxItem haben wir ein StackPanel hinzugefügt, in welchem ein Bild und ein TextBlock dargestellt wird. Das gibt uns die volle Kontrolle über die Inhalte und die Textdarstellung. Das ist in dem Screenshot zu sehen, wo sowohl Textfarbe als auch das Bild den Farbwert anzeigen.

Data binding einer ComboBox

Wie in den ersten Beispielen zu erkennen ist, ist das händische Erstellen von Inhalten eines ComboBox Kontrollelements mit XAML sehr einfach. Aber man wird bald in die die Situation kommen, wo die Inhalte durch eine andere Datenquelle, wie zum Beispiel einer Datenbank oder einer im Speicher befindlichen Liste definiert werden. Mittels WPF data binding und einer selbst erzeugten Vorlage können wir sehr einfach eine Liste an Farben, samt einer Vorschau der Farbe, erzeugen:

<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();
		}
	}
}

So gesehen ist es ziemlich einfach: Im Code-behind erzeuge ich mir eine Liste aller Farben aus der Colors Klasse mittels sogenannter Reflection. Diese weise ich der ItemsSource Eigenschaft der ComboBox zu, welche diese dann mit Hilfe der Vorlage darstellt, welche im XAML Teil definiert wurde.

Jedes Element besteht, wie in der ItemTemplate definiert, aus einem StackPanel mit einem Rechteck und einem Textblock welches jeweils an den Farbwert gebunden ist. Das gibt uns mit geringem Aufwand eine vollständige Liste an Farben - und es sieht auch noch ziemlich gut aus, oder?

IsEditable

In den ersten Beispielen konnte der Nutzer nur aus der von uns definierten Liste auswählen. Aber eine der coolen Eigenschaften der ComboBox ist es, dass sie es dem Nutzer erlaubt sowohl aus der Liste zu wählen, als auch einen eigenen Wert einzutragen. Das ist in den Situationen besonders nützlich in denen man dem Nutzer eine gewisse Hilfestellung in Form von vorher festgelegten Werten geben möchte. Und trotzdem gibt man ihm die Möglichkeit den eigenen Wert per Hand einzutragen. Das wird alles durch die IsEditable Eigenschaft festgelegt, welche das Verhalten und das Aussehen der ComboBox ziemlich verändert:

<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>

Wie du sehen kannst, kann ich einen komplett anderen Wert eingeben oder aber einen aus der Liste auswählen. Wenn ich einen aus der Liste wähle überschreibt er einfach den Text in der ComboBox.

Als kleines Extra kann die ComboBox dem Nutzer bereits beim Eintippen helfen einen bereits existierenden Wert auszuwählen. Das kann im nächsten Screenshot gesehen werden, wo ich "Co" eingegeben habe:

Standardmäßig beachtet die Vervollständigung Groß- und Kleinschreibung nicht, aber das kann erzwungen werden indem IsTextSearchCaseSensitive auf True gesetzt wird. Sollte die Autovervollständigung gar nicht gebraucht werden, kann sie deaktiviert werden indem man IsTextSearchEnabled auf False setzt.

Arbeiten mit dem ausgewählten Element

Eine wichtige Eigenschaft der ComboBox ist, dass man in der Lage ist das vom Nutzer ausgewählte Element auszulesen und es sogar per Code zu setzen. Im nächsten Beispiel habe ich das data bound ComboBox Beispiel von vorher wiederverwendet und ein paar Knöpfe hinzugefügt um die Auswahl der ComboBox zu steuern. Zusätzlich habe ich den SelectionChanged Event verwendet um mitzubekommen, wenn sich das ausgewählte Element verändert hat um darauf zu reagieren. Egal ob es per Code oder vom Nutzer geändert wurde.

Hier ist das Beispiel:

<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);
		}
	}
}

Der interessante Teil dieses Beispiels sind die drei event handler für die drei Knöpfe, sowie der SelectionChanged event handler. In den ersten beiden wählen wir das nächste bzw. das vorhergehende Element aus indem wir die SelectedIndex Eigenschaft auslesen und entweder eins addieren oder abziehen. Ziemlich einfach und leicht damit zu arbeiten.

Im dritten event handler benutzen wir SelectedItem um ein bestimmtes Element über seinen Wert auszuwählen. Ich spendiere hier etwas mehr Arbeit (mit Hilfe von .NET reflection), da die ComboBox hier an eine Liste von Eigenschaften, die eine Farbe repräsentieren, an Stelle einer einfachen Liste von Farben, gebunden ist. Aber im Grunde läuft alles darauf hinaus, dass einer der Werte an die SelectedItem Eigenschaft weitergegeben wird.

Im vierten und letzten event handler reagiere ich, wenn der ausgewählte Inhalt geändert wird. Wenn das passiert lese ich die ausgewählte Farbe (wiederum mittels Reflection, wie oben beschrieben) und erzeuge mit ihr einen neuen SolidColorBrush für den Hintergrund des Fensters. Was das bewirkt kann man am Screenshot erkennen.

Wenn mit einer editierbaren ComboBox (IsEditable Eigenschaft ist auf True gesetzt) gearbeitet wird, kann die Text Eigenschaft ausgelesen werden um zu wissen, welchen Wert der Nutzer eingetragen bzw. ausgewählt hat.


This article has been fully translated into the following languages: Is your preferred language not on the list? Click here to help us translate this article into your language!