TOC

This article has been localized into German by the community.

Dialoge:

Erstellen eines benutzerdefinierten Eingabedialogs

In den letzten Arikeln haben wir die vorhandenen Dialoge von WPF verwendet, aber einen eigenen zu Erstellen ist fast genau so einfach. Man muss nur ein Window erstellen, die benötigten Steuerelemente einfügen und es anzeigen.

Es gibt allerdings einige Dinge die man beim Erstellen von Dialogen beachten sollte um sicherzustellen, dass sich die Anwendung wie andere Windows Anwendungen verhält. In diesem Artikel erstellen wir einen sehr einfachen Dialog um dem Benutzer eine Frage zu stellen und die Antwort zurückzugeben. Währenddessen gehen wir auf einige Richtlinien ein, denen man folgen sollte.

Designen des Dialogs

Für speziell diesen Dialog wollte ich ein Label, dass dem Benutzer sagt welche Informationen wir von ihm/ihr brauchen, eine TextBox für die Eingabe der Antwort und dann die normalen OK und Abbrechen Buttons. Ich habe dem Dialog ein Icon hinzugefügt damit er besser aussieht. Hier ist das Ergebnis:

Und hier ist der Code für den Dialog:

<Window x:Class="WpfTutorialSamples.Dialogs.InputDialogSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Input" SizeToContent="WidthAndHeight" WindowStartupLocation="CenterScreen"
        ContentRendered="Window_ContentRendered">
    <Grid Margin="15">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <Image Source="/WpfTutorialSamples;component/Images/question32.png" Width="32" Height="32" Grid.RowSpan="2" Margin="20,0" />

        <Label Name="lblQuestion" Grid.Column="1">Question:</Label>
        <TextBox Name="txtAnswer" Grid.Column="1" Grid.Row="1" MinWidth="250">Answer</TextBox>

        <WrapPanel Grid.Row="2" Grid.ColumnSpan="2" HorizontalAlignment="Right" Margin="0,15,0,0">
            <Button IsDefault="True" Name="btnDialogOk" Click="btnDialogOk_Click" MinWidth="60" Margin="0,0,10,0">_Ok</Button>
            <Button IsCancel="True" MinWidth="60">_Cancel</Button>
        </WrapPanel>
    </Grid>
</Window>
using System;
using System.Windows;

namespace WpfTutorialSamples.Dialogs
{
	public partial class InputDialogSample : Window
	{
		public InputDialogSample(string question, string defaultAnswer = "")
		{
			InitializeComponent();
			lblQuestion.Content = question;
			txtAnswer.Text = defaultAnswer;
		}

		private void btnDialogOk_Click(object sender, RoutedEventArgs e)
		{
			this.DialogResult = true;
		}

		private void Window_ContentRendered(object sender, EventArgs e)
		{
			txtAnswer.SelectAll();
			txtAnswer.Focus();
		}

		public string Answer
		{
			get { return txtAnswer.Text; }
		}
	}
}

Der Code ist ziemlich einfach, aber hier sind einige Dinge der man besondere Beachtung schenken sollte:

XAML

Im XAML Teil habe ich ein Grid für die Steuerelemente benutzt, nichts besonderes also. Ich habe die Width und Height Eigenschaften des Window entfernt und stattdessen eingestellt, dass es sich automatisch an den Inhalt anpasst. Das ist in einem Dialog sinnvoll, sodass man nicht alles passend einstellen muss um ihn korrekt darzustellen. Man sollte Margin und Minimum Size verwenden um sicherzustellen, dass alles so aussieht wie man es möchte, der Benutzer aber noch die Möglichkeit hat die Größe anzupassen.

Eine andere Eigenschaft die ich am Window verändert habe ist die WindowStartupLocation Eigenschaft. Für einen Dialog wie diesen und vermutlich für fast alle anderen Nicht-Hauptfenster, sollte man diesen Wert zu CenterScreen order CenterOwner ändern um das Standardverhalten, wo das Fenster auftauchen soll, in eine von Windows bestimmte Position zu ändern, außer man möchte manuell die Top und Left Eigenschaften anpassen.

Außerdem sollte man folgende beiden Eigenschaften von den Buttons beachten: IsCancel und IsDefault. IsCancel sagt WPF, dass, wenn ein Benutzer auf diesen Button klickt, die DialogResult Eigenschaft des Window auf false gesetzt werden soll, was auch beim Schließen des Fensters passiert. Das ermöglicht es dem Benutzer auch mit der Esc-Taste auf der Tastatur das Fenster zu schließen, was in einem Windows Dialog immer möglich sein sollte.

Die IsDefault Eigenschaft setzt den Fokus auf den OK Button und aktiviert außerdem diesen Button, wenn der Benutzer die Enter-Taste auf der Tastatur drückt. Allerdings wird ein EventHandler benötigt um die DialogResult Eigenschaft zu setzen - später mehr dazu.

Code-behind

Im Code-behind habe ich den Konstruktor abgeändert damit er zwei Parameter annimmt, wobei einer davon optional ist. Das erlaubt es uns die Frage und die Standardantwort - wenn vorhanden - in die dafür vorhergesehenen UI Steuerelemente zu setzen.

Der OK Button hat einen EventHandler der dafür sorgt, dass die Eigenschaft DialogResult von dem Window auf true setzt, wenn er geklickt wird. Dadurch wird dem Ersteller des Dialogs signalisiert, dass der Benutzer den eingegebenen Wert akzeptiert. Wir haben keinen für den Cancel Button weil WPF das für uns erledigt, wenn wir die IsCancel Eigenschaft, wie oben beschrieben, auf true setzen.

Um beim Anzeigen des Dialogs die TextBox zu fokussieren, verwende ich das ContentRendered Event, bei dem ich den ganzen Text im Steuerelement auswähle und dann den Fokus setze. Wenn ich nur den Fokus setzen wollte, hätte ich die FocusManager.FocusedElement Eigenschaft auf dem Window setzen können. In diesem Fall möchte ich aber zusätzlich den Text auswählen um dem Benutzer das sofortig Überschreiben der Standardantwort zu ermöglichen.

Ein letztes Detail ist die Answer Eigenschaft. Dadurch erhält man Zugriff zum eingegebenen Wert der TextBox. Allerdings ist es gängige Praxis eine Eigenschaft mit dem Rückgabewert des Dialogs zu erstellen, anstatt direkt auf das Steuerelement von außerhalb zuzugreifen. Das erlaubt es uns außerdem den Rückgabewert zu verändern, wenn nötig.

Den Dialog verwenden

Jetzt sind wir bereit den Dialog tatsächlich zu verwenden. Es ist eine sehr einfache Aufgabe, also habe ich eine kleine Anwendung zum testen erstellt. Hier ist der Code:

<Window x:Class="WpfTutorialSamples.Dialogs.InputDialogAppSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="InputDialogAppSample" Height="150" Width="300">
    <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
        <TextBlock>Hello, world. My name is:</TextBlock>
        <TextBlock Name="lblName" Margin="0,10" TextAlignment="Center" FontWeight="Bold">[No name entered]</TextBlock>
        <Button Name="btnEnterName" Click="btnEnterName_Click">Enter name...</Button>
    </StackPanel>
</Window>
using System;
using System.Windows;

namespace WpfTutorialSamples.Dialogs
{
	public partial class InputDialogAppSample : Window
	{
		public InputDialogAppSample()
		{
			InitializeComponent();
		}

		private void btnEnterName_Click(object sender, RoutedEventArgs e)
		{
			InputDialogSample inputDialog = new InputDialogSample("Please enter your name:", "John Doe");
			if(inputDialog.ShowDialog() == true)
				lblName.Text = inputDialog.Answer;
		}
	}
}

Hier gibt es nichts spezielles, nur ein paar TextBlock Steuerelemente und ein Button um den Dialog aufzurufen. Im Click EventHandler instanziieren wir das InputDialogSample Fenster, welches eine Frage und Standardantwort bereitstellt. Dann verwenden wir die ShowDialog() Methode um den Dialog anzuzeigen. Für einen Dialog wie diesen sollte man immer die ShowDialog() Methode statt der Show() Methode verwenden.

Wenn das Ergebnis des Dialogs true ist, was bedeutet das der Benutzer auf den OK Button geklickt hat, wird das Ergebnis dem TextBlock zugewiesen. Das ist alles!


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!