WPF: создание диалогового окна / приглашения
Мне нужно создать диалоговое окно / приглашение, включая текстовое поле для ввода пользователем. Моя проблема в том, как получить текст после подтверждения диалога? Обычно я бы сделал класс для этого, который сохранил бы текст в свойстве. Однако я хочу сделать дизайн диалогового окна с помощью XAML. Поэтому мне каким - то образом придется расширить код XAML, чтобы сохранить содержимое текстового поля в свойстве, но я думаю, что это невозможно с чистым XAML. Каков был бы лучший способ понять, что я хотел бы сделать? Как построить диалог, который может быть определен из XAML, но все еще может каким-то образом возвращать входные данные? Спасибо за любую подсказку!
4 ответов:
"ответственный" ответ был бы для меня, чтобы предложить построить ViewModel для диалогового окна и использовать двустороннюю привязку данных в текстовом поле, чтобы ViewModel имел какое-то свойство "ResponseText" или что нет. Это достаточно легко сделать,но, вероятно, излишне.
прагматичным ответом было бы просто дать вашему текстовому полю x: Name, чтобы оно стало членом и предоставило текст как свойство в вашем коде за классом следующим образом:
<!-- Incredibly simplified XAML --> <Window x:Class="MyDialog"> <StackPanel> <TextBlock Text="Enter some text" /> <TextBox x:Name="ResponseTextBox" /> <Button Content="OK" Click="OKButton_Click" /> </StackPanel> </Window>тогда в вашем коде позади...
partial class MyDialog : Window { public MyDialog() { InitializeComponent(); } public string ResponseText { get { return ResponseTextBox.Text; } set { ResponseTextBox.Text = value; } } private void OKButton_Click(object sender, System.Windows.RoutedEventArgs e) { DialogResult = true; } }затем использовать его...
var dialog = new MyDialog(); if (dialog.ShowDialog() == true) { MessageBox.Show("You said: " + dialog.ResponseText); }
Я просто добавляю статический метод, чтобы вызвать его как MessageBox:
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" x:Class="utils.PromptDialog" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" WindowStartupLocation="CenterScreen" SizeToContent="WidthAndHeight" MinWidth="300" MinHeight="100" WindowStyle="SingleBorderWindow" ResizeMode="CanMinimize"> <StackPanel Margin="5"> <TextBlock Name="txtQuestion" Margin="5"/> <TextBox Name="txtResponse" Margin="5"/> <PasswordBox Name="txtPasswordResponse" /> <StackPanel Orientation="Horizontal" Margin="5" HorizontalAlignment="Right"> <Button Content="_Ok" IsDefault="True" Margin="5" Name="btnOk" Click="btnOk_Click" /> <Button Content="_Cancel" IsCancel="True" Margin="5" Name="btnCancel" Click="btnCancel_Click" /> </StackPanel> </StackPanel> </Window>и код:
public partial class PromptDialog : Window { public enum InputType { Text, Password } private InputType _inputType = InputType.Text; public PromptDialog(string question, string title, string defaultValue = "", InputType inputType = InputType.Text) { InitializeComponent(); this.Loaded += new RoutedEventHandler(PromptDialog_Loaded); txtQuestion.Text = question; Title = title; txtResponse.Text = defaultValue; _inputType = inputType; if (_inputType == InputType.Password) txtResponse.Visibility = Visibility.Collapsed; else txtPasswordResponse.Visibility = Visibility.Collapsed; } void PromptDialog_Loaded(object sender, RoutedEventArgs e) { if (_inputType == InputType.Password) txtPasswordResponse.Focus(); else txtResponse.Focus(); } public static string Prompt(string question, string title, string defaultValue = "", InputType inputType = InputType.Text) { PromptDialog inst = new PromptDialog(question, title, defaultValue, inputType); inst.ShowDialog(); if (inst.DialogResult == true) return inst.ResponseText; return null; } public string ResponseText { get { if (_inputType == InputType.Password) return txtPasswordResponse.Password; else return txtResponse.Text; } } private void btnOk_Click(object sender, RoutedEventArgs e) { DialogResult = true; Close(); } private void btnCancel_Click(object sender, RoutedEventArgs e) { Close(); } }Так что вы можете назвать это так:
string repeatPassword = PromptDialog.Prompt("Repeat password", "Password confirm", inputType: PromptDialog.InputType.Password);
отличный ответ Джоша, все заслуги перед ним, я немного изменил его на это, однако:
MyDialog Xaml
<StackPanel Margin="5,5,5,5"> <TextBlock Name="TitleTextBox" Margin="0,0,0,10" /> <TextBox Name="InputTextBox" Padding="3,3,3,3" /> <Grid Margin="0,10,0,0"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <Button Name="BtnOk" Content="OK" Grid.Column="0" Margin="0,0,5,0" Padding="8" Click="BtnOk_Click" /> <Button Name="BtnCancel" Content="Cancel" Grid.Column="1" Margin="5,0,0,0" Padding="8" Click="BtnCancel_Click" /> </Grid> </StackPanel>MyDialog Код За
public MyDialog() { InitializeComponent(); } public MyDialog(string title,string input) { InitializeComponent(); TitleText = title; InputText = input; } public string TitleText { get { return TitleTextBox.Text; } set { TitleTextBox.Text = value; } } public string InputText { get { return InputTextBox.Text; } set { InputTextBox.Text = value; } } public bool Canceled { get; set; } private void BtnCancel_Click(object sender, System.Windows.RoutedEventArgs e) { Canceled = true; Close(); } private void BtnOk_Click(object sender, System.Windows.RoutedEventArgs e) { Canceled = false; Close(); }и назовите его где-нибудь еще
var dialog = new MyDialog("test", "hello"); dialog.Show(); dialog.Closing += (sender,e) => { var d = sender as MyDialog; if(!d.Canceled) MessageBox.Show(d.InputText); }
не нужно любой из этих других причудливых ответов. Ниже приведен упрощенный пример, который не имеет всех
Margin,Height,Widthнабор свойств в XAML, но должно быть достаточно, чтобы показать, как это сделать на базовом уровне.XAML
ПостроитьWindowстраница, как вы обычно и добавить свои поля к нему, сказатьLabelиTextBoxуправление внутри aStackPanel:<StackPanel Orientation="Horizontal"> <Label Name="lblUser" Content="User Name:" /> <TextBox Name="txtUser" /> </StackPanel>затем создайте стандартный
Buttonдля отправки ("ОК" или "отправить") и кнопку" Отмена", если вам нравится:<StackPanel Orientation="Horizontal"> <Button Name="btnSubmit" Click="btnSubmit_Click" Content="Submit" /> <Button Name="btnCancel" Click="btnCancel_Click" Content="Cancel" /> </StackPanel>Код
Вы добавитеClickфункции обработчика событий в коде, но когда вы идете туда, сначала объявите общедоступную переменную, где вы будете хранить значение текстового поля:public static string strUserName = String.Empty;затем для функций обработчика событий (щелкните правой кнопкой мыши
Clickфункция на кнопке XAML, выберите "Перейти к определению", он создаст его для вас), вы нужна проверка, чтобы увидеть, если ваш ящик пуст. Вы храните его в переменной, если это не так, и закройте окно:private void btnSubmit_Click(object sender, RoutedEventArgs e) { if (!String.IsNullOrEmpty(txtUser.Text)) { strUserName = txtUser.Text; this.Close(); } else MessageBox.Show("Must provide a user name in the textbox."); }Вызов Его С Другой Страницы
Вы думаете, если я закрою окно с этимthis.Close()там, наверху, моя ценность исчезла, верно? нет!! я узнал это с другого сайта: http://www.dreamincode.net/forums/topic/359208-wpf-how-to-make-simple-popup-window-for-input/у них было подобное пример к этому (я очистил его немного) о том, как открыть ваш
Windowот другого и получить значения:public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void btnOpenPopup_Click(object sender, RoutedEventArgs e) { MyPopupWindow popup = new MyPopupWindow(); // this is the class of your other page //ShowDialog means you can't focus the parent window, only the popup popup.ShowDialog(); //execution will block here in this method until the popup closes string result = popup.strUserName; UserNameTextBlock.Text = result; // should show what was input on the other page } }Отменить Кнопке
Ты думаешь, А как насчет этой кнопки отмены? Поэтому мы просто добавляем еще одну общедоступную переменную обратно в наше всплывающее окно code-behind:public static bool cancelled = false;и давайте включим наш
btnCancel_Clickобработчик событий, и сделать одно изменение кbtnSubmit_Click:private void btnCancel_Click(object sender, RoutedEventArgs e) { cancelled = true; strUserName = String.Empty; this.Close(); } private void btnSubmit_Click(object sender, RoutedEventArgs e) { if (!String.IsNullOrEmpty(txtUser.Text)) { strUserName = txtUser.Text; cancelled = false; // <-- I add this in here, just in case this.Close(); } else MessageBox.Show("Must provide a user name in the textbox."); }и тогда мы читаем эту переменную в наши
MainWindowbtnOpenPopup_Clickсобытие:private void btnOpenPopup_Click(object sender, RoutedEventArgs e) { MyPopupWindow popup = new MyPopupWindow(); // this is the class of your other page //ShowDialog means you can't focus the parent window, only the popup popup.ShowDialog(); //execution will block here in this method until the popup closes // **Here we find out if we cancelled or not** if (popup.cancelled == true) return; else { string result = popup.strUserName; UserNameTextBlock.Text = result; // should show what was input on the other page } }длинный ответ, но я хотел показать, как легко это использовать
public staticпеременные. НетDialogResult, нет возвращаемых значений, ничего. Просто откройте окно, сохраните свои значения с помощью событий кнопки во всплывающем окне, а затем извлеките их впоследствии в функции главного окна.
Comments