WPF:创build一个对话框/提示
我需要创build一个对话框/提示包括用户input的文本框。 我的问题是,确认对话框后如何获取文本? 通常我会为此做一个类,将文本保存在一个属性中。 不过我想用XAML来devise对话框。 所以我会不知何故必须扩展XAML代码以将TextBox的内容保存在一个属性中 – 但我想这对于纯XAML来说是不可能的。 什么是最好的方法来实现我想要做的事情? 如何构build一个可以从XAML定义的对话框,但仍然可以返回input? 感谢任何提示!
“负责任”的答案是我build议为对话框build立一个ViewModel,并在TextBox上使用双向数据绑定,以便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);
Josh的伟大回答,都归功于他,然而我略微修改了这个:
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); }
你不需要任何其他奇特的答案。 下面是一个简单的例子,它没有在XAML中设置所有的Margin
, Height
, Width
属性,但应该足以展示如何在基本级别完成这项工作。
XAML
像通常一样build立一个Window
页面,并添加你的字段,比如在一个StackPanel
一个Label
和TextBox
控件:
<StackPanel Orientation="Horizontal"> <Label Name="lblUser" Content="User Name:" /> <TextBox Name="txtUser" /> </StackPanel>
然后创build一个标准的提交Button
(“确定”或“提交”)和一个“取消”button,如果你喜欢:
<StackPanel Orientation="Horizontal"> <Button Name="btnSubmit" Click="btnSubmit_Click" Content="Submit" /> <Button Name="btnCancel" Click="btnCancel_Click" Content="Cancel" /> </StackPanel>
代码隐藏
您将在代码隐藏中添加Click
事件处理函数,但是当您到达那里时,首先声明一个公用variables,您将在其中存储您的文本框值:
public static string strUserName = String.Empty;
然后,对于事件处理函数(右键单击XAMLbutton上的Click
函数,select“Go To Definition”,它会为你创build),你需要检查一下你的方框是否为空。 如果不存在,则将其存储在variables中,然后closures窗口:
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."); }
从另一页调用它
你在想,如果我用这个closures我的窗户。 this.Close()
在那里,我的价值消失了,对吧? 没有!! 我从另一个网站find了这个: http : //www.dreamincode.net/forums/topic/359208-wpf-how-to-make-simple-popup-window-for-input/
他们有一个类似的例子(我清理了一下)如何从另一个Window
打开你的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 } }
取消button
你在想,那么取消button呢? 所以我们只是在我们的popup窗口代码后面添加另一个公共variables:
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."); }
然后我们在MainWindow
btnOpenPopup_Click
事件中读取这个variables:
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
variables。 没有DialogResult
,没有返回值,什么也没有。 只要打开窗口,用popup窗口中的button事件存储你的值,然后在主窗口函数中检索它们。