TOC

This article has been localized into Danish by the community.

Dialoger:

Oprettelse af en brugerdefineret input-dialog

I de sidste par artikler, har vi set på at bruge de indbyggede dialoger i WPF, men oprettelse af dine egne er næsten lige så let. Faktisk behøver du kun oprette et Window, placere de nødvendige kontroller og derefter vise det.

Men der er nogle få ting, du skal huske, når du opretter dialoger, for at være sikker på, at din applikation opfører sig som andre Windows applikationer. I denne artikel vil vi oprette en meget simpel dialog til at stille brugeren et spørgsmål og derefter returnere svaret mens, vi diskuterer de forskellige gode praksis, du bør følge.

Design af dialogen

Til denne specifikke dialog, vil jeg bare have et Label til at fortælle brugeren hvilken information, vi har brug for fra ham/hende, en TextBox til indtastning af svaret, og derefter de sædvanlige Ok og Annuller knapper. Jeg besluttede at tilføje et ikon til dialogen også, for bedre design. Her er slutresultatet:

Og her er koden til dialogen:

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

Koden er ret simpel, men her er de ting, du skal være opmærksom på:

XAML

I XAML-delen har jeg brugt et Grid til layout af kontrollerne - ikke noget fancy her. Jeg har fjernet Width og Height egenskaberne på vinduet og i stedet sat det til automatisk at tilpasse størrelse efter indholdet - dette giver mening i en dialog, så du ikke behøver at finjustere størrelsen for at få alt til at se ordentligt ud. I stedet bruges marginer og mindstestørrelser for at sikre, at tingene ser ud, som du vil have dem til, mens du stadig tillader brugeren at skifte størrelse på dialogen.

En anden egenskab, jeg har ændret på Window, er WindowStartupLocation egenskaben. Til en dialog som denne, og sikkert også de fleste andre ikke-primære vinduer, bør denne ændres til CenterScreen eller CenterOwner, for at ændre standardopførslen, hvor dit vindue vil blive placeret et sted, Windows bestemmer, med mindre du manuelt angiver Top og Left egenskaberne for det.

Vær også særlig opmærksom på de to egenskaber, jeg har brugt på dialogknapperne: IsCancel og IsDefault. IsCancel fortæller WPF, at hvis brugeren klikker på denne knap, skal DialogResult på Window sættes til false, hvilket også vil lukke vinduet. Det sikrer også, at brugeren kan trykke på Esc tasten på tastaturet for at lukke vinduet, hvilket altid skal være muligt i en Windows dialog.

IsDefault egenskaben giver fokus til Ok knappen, og sikrer også, at hvis brugeren trykker på Enter knappen på tastaturet, vil denne knap blive aktiveret. Det er dog nødvendigt med en event handler for at sætte DialogResult på den, som beskrevet senere.

Code-behind

I code-behind ændrede jeg konstruktøren til at tage to parametre, hvor den ene er valgfri. Dette tillader os at placere spørgsmålet og et standardsvar, hvis angivet, i de respektive UI kontroller.

Ok knappen har en event handler, som sørger for, at den specielle DialogResult egenskab på Window bliver sat til true, når der trykkes på knappen, for at signalere til dialogens skabere, at brugeren har accepteret den indtastede værdi. Vi behøver ikke have en for Cancel knappen, fordi WPF håndterer det for os, når vi sætter IsCancel egenskaben til true, som beskrevet ovenfor.

For at sætte fokus på TextBox ved åbning af dialogen, har jeg abonneret på ContentRendered hændelsen, hvor jeg vælger al tekst i kontrollen og derefter giver fokus. Hvis jeg bare ønskede at give fokus, kunne jeg have brugt den FocusManager.FocusedElement tilknyttede egenskab på Window, men i dette tilfælde ønsker jeg også at vælge teksten, så brugeren med det samme kan overskrive standardsvaret (hvis der er et).

En sidste detalje er Answer egenskaben, som jeg har implementeret. Den giver ganske enkelt adgang til den indtastede værdi i TextBox kontrollen, men det er god praksis at definere en egenskab med returværdi(er) fra dialogen i stedet for direkte adgang til kontrollerne uden for vinduet. Dette tillader dig også at have indflydelse på returværdien før, den returneres, hvis det er nødvendigt.

Brug af dialogen

Med alt ovenstående på plads, er vi nu klar til faktisk at bruge vores dialog. Det er en meget simpel opgave, så jeg har lavet en lille applikation til at teste den. Her er koden:

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

Der er ikke noget specielt i det - bare et par TextBlock kontroller og en knap til at åbne dialoggen. I Click event handleren instantierer vi InputDialogSample vinduet, giver et spørgsmål og et standard svar, og derefter bruger vi ShowDialog() metoden for at vise den - du bør altid bruge ShowDialog() metoden og ikke bare Show() til en modal dialog som denne.

Hvis resultatet af dialogen er true, hvilket betyder, at brugeren har aktiveret Ok knappen enten ved at klikke på den eller trykke Enter, bliver resultatet tildelt til navne Label. Det er alt, der er i det!


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!