This article has been localized into Czech by the community.
Tvorba vlastního vstupního dialogu
V posledních několika článcích jsme se podívali na používání vestavěných dialogů WPF, ale vytvoření vlastního dialogu je téměř stejně snadné. Ve skutečnosti stačí vytvořit okno, umístit do něj požadované ovládací prvky a pak ho zobrazit.
Existuje však několik věcí, které byste si měli pamatovat při vytváření dialogů, abyste zajistili, že vaše aplikace se bude chovat jako ostatní aplikace Windows. V tomto článku vytvoříme velmi jednoduchý dialog, který položí uživateli otázku a poté vrátí odpověď, zatímco budeme diskutovat o různých dobrých postupech, které byste měli dodržovat.
Návrh dialogu
Pro tento konkrétní dialog jsem chtěl pouze popisek (Label), který uživateli řekne, které informace od něj potřebujeme, textové pole (TextBox) pro zadání odpovědi a pak obvyklá tlačítka Ok a Zrušit. Rozhodl jsem se také přidat do dialogu ikonu, aby vypadal lépe. Zde je výsledný vzhled:
A zde je kód pro 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; }
}
}
}
Kód je celkem jednoduchý, ale zde jsou věci, kterým byste měli věnovat zvláštní pozornost:
XAML
V části XAML jsem použil Grid pro rozložení ovládacích prvků - nic složitého. Odstranil jsem vlastnosti Šířka a Výška okna a místo toho jsem ho nastavil tak, aby se automaticky přizpůsobilo obsahu - to dává v dialogu smysl, takže nemusíte přesně ladit velikost. Místo toho použijte okraje a minimální velikosti, abyste zajistili, že věci vypadají tak, jak chcete, a zároveň umožnili uživateli změnit velikost dialogu.
Další vlastnost, kterou jsem změnil na okně, je vlastnost WindowStartupLocation. Pro dialog jako tento a pravděpodobně pro většinu ostatních nehlavních oken byste měli tuto hodnotu změnit na CenterScreen nebo CenterOwner, aby se změnilo výchozí chování, kdy se vaše okno objeví na pozici rozhodnuté operačním systémem Windows, pokud pro něj ručně nespecifikujete vlastnosti Top a Left.
Věnujte také zvláštní pozornost dvěma vlastnostem, které jsem použil u dialogových tlačítek: IsCancel a IsDefault. IsCancel říká WPF, že pokud uživatel klikne na toto tlačítko, měl by být DialogResult okna nastaven na false, což také zavře okno. To také zajišťuje, že uživatel může stisknout klávesu Esc na klávesnici, aby okno zavřel, což by mělo být v dialogu Windows vždy možné.
Vlastnost IsDefault dává fokus tlačítku Ok a také zajišťuje, že pokud uživatel stiskne klávesu Enter, toto tlačítko je aktivováno. Pro nastavení DialogResult je však potřeba obslužná rutina událostí, jak je popsáno později.
Code-behind
V Code-behind jsem změnil konstruktor tak, aby přijímal dva parametry, přičemž jeden je volitelný. To nám umožňuje umístit otázku a výchozí odpověď, pokud je poskytnuta, do určených uživatelských ovládacích prvků.
Tlačítko OK má obslužnou rutinu události, která zajišťuje, že speciální vlastnost DialogResult okna je nastavena na true při kliknutí, aby signalizovala iniciátoru dialogu, že uživatel přijal zadanou hodnotu. Pro tlačítko Zrušit obslužnou rutinu nemáme, protože WPF to za nás zpracuje, když nastavíme vlastnost IsCancel na true, jak bylo popsáno výše.
Abych při zobrazení dialogu dal fokus na TextBox, přihlásil jsem se k události ContentRendered, kde vyberu veškerý text v ovládacím prvku a poté mu dám fokus. Pokud bych pouze chtěl dát fokus, mohl bych použít připojenou vlastnost FocusManager.FocusedElement na okně, ale v tomto případě také chci vybrat text, aby uživatel mohl okamžitě přepsat odpověď poskytnutou ve výchozím nastavení (pokud existuje).
Posledním detailem je vlastnost Answer, kterou jsem implementoval. Jednoduše poskytuje přístup k zadané hodnotě ovládacího prvku TextBox, ale je dobrým zvykem poskytnout vlastnost s návratovou hodnotou/hodnotami dialogu místo přímého přístupu k ovládacím prvkům zvenčí okna. To vám také umožňuje ovlivnit návratovou hodnotu před jejím vrácením, pokud je to potřeba.
Použití dialogu
S výše uvedeným nastavením jsme nyní připraveni skutečně používat náš dialog. Je to velmi jednoduchý úkol, takže jsem pro testování vytvořil malou aplikaci. Zde je kód:
<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;
}
}
}
Není to nic speciálního - jen pár ovládacích prvků TextBlock a tlačítko pro vyvolání dialogu. V obslužné rutině události Click vytvoříme okno InputDialogSample, poskytneme otázku a výchozí odpověď a poté použijeme metodu ShowDialog() k jeho zobrazení - pro modální dialog jako tento byste měli vždy použít metodu ShowDialog() a ne jen Show().
Pokud je výsledek dialogu true, což znamená, že uživatel aktivoval tlačítko Ok buď kliknutím na něj nebo stisknutím klávesy Enter, výsledek je přiřazen k popisku jména. To je vše!