visual studio que puede programacion presentacion hacer ejemplos desventajas con animaciones wpf dialog prompt

que - visual studio wpf



WPF: Crear un diálogo/prompt (4)

Gran respuesta de Josh, todo el crédito para él, sin embargo, lo modifiqué ligeramente a esto:

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>

Código de MyDialog detrás

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

Y llámalo a otro lado

var dialog = new MyDialog("test", "hello"); dialog.Show(); dialog.Closing += (sender,e) => { var d = sender as MyDialog; if(!d.Canceled) MessageBox.Show(d.InputText); }

Necesito crear un Dialog / Prompt que incluya TextBox para la entrada del usuario. Mi problema es cómo obtener el texto después de haber confirmado el diálogo. Usualmente haría una clase para esto que guardara el texto en una propiedad. Sin embargo, quiero diseñar el Diálogo utilizando XAML. Así que de alguna manera tendría que extender el código XAML para guardar el contenido del TextBox en una propiedad, pero supongo que eso no es posible con XAML puro. ¿Cuál sería la mejor manera de darme cuenta de lo que me gustaría hacer? ¿Cómo crear un diálogo que se puede definir desde XAML pero que de alguna manera puede devolver la entrada? Gracias por cualquier pista!


La respuesta "responsable" sería que sugiriera construir un ViewModel para el diálogo y usar un enlace de datos bidireccional en el TextBox para que ViewModel tuviera alguna propiedad de "ResponseText" o no. Esto es bastante fácil de hacer, pero probablemente exagerado.

La respuesta pragmática sería simplemente darle a su cuadro de texto una x: Nombre para que se convierta en miembro y exponer el texto como una propiedad en su código detrás de la clase, de esta manera:

<!-- 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>

Luego en tu código detrás ...

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

Entonces para usarlo ...

var dialog = new MyDialog(); if (dialog.ShowDialog() == true) { MessageBox.Show("You said: " + dialog.ResponseText); }


No necesita NINGUNA de estas otras respuestas elegantes. A continuación se muestra un ejemplo simplista que no tiene todas las propiedades de Margin , Height , Width establecidas en el XAML, pero debería ser suficiente para mostrar cómo hacerlo en un nivel básico.

XAML
Cree una página de Window como lo haría normalmente y agregue sus campos a ella, por ejemplo, un control Label y TextBox dentro de un StackPanel :

<StackPanel Orientation="Horizontal"> <Label Name="lblUser" Content="User Name:" /> <TextBox Name="txtUser" /> </StackPanel>

Luego, cree un Button estándar para Envío ("Aceptar" o "Enviar") y un botón "Cancelar" si lo desea:

<StackPanel Orientation="Horizontal"> <Button Name="btnSubmit" Click="btnSubmit_Click" Content="Submit" /> <Button Name="btnCancel" Click="btnCancel_Click" Content="Cancel" /> </StackPanel>

Código detrás
Agregará las funciones del controlador de eventos Click en el código subyacente, pero cuando vaya allí, primero, declare una variable pública donde almacenará el valor de su cuadro de texto:

public static string strUserName = String.Empty;

Luego, para las funciones del controlador de eventos (haga Click con el botón derecho en la función Click en el botón XAML, seleccione "Ir a definición", se creará por usted), necesita una verificación para ver si su casilla está vacía. Lo almacena en su variable si no es así, y cierra su ventana:

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."); }

Llamar desde otra página
Estás pensando, si cierro mi ventana con esto. this.Close() allá arriba, mi valor se ha ido, ¿verdad? ¡¡NO!! Encontré esto en otro sitio: http://www.dreamincode.net/forums/topic/359208-wpf-how-to-make-simple-popup-window-for-input/

Tenían un ejemplo similar a esto (lo limpié un poco) de cómo abrir su Window desde otra y recuperar los valores:

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

Botón Cancelar
Estás pensando, ¿y qué hay del botón Cancelar? Así que simplemente agregamos otra variable pública en nuestro código emergente de la ventana emergente:

public static bool cancelled = false;

E btnCancel_Click nuestro controlador de eventos btnCancel_Click y hagamos un cambio a 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."); }

Y luego, simplemente leemos esa variable en nuestro evento MainWindow btnOpenPopup_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 } }

Respuesta larga, pero quería mostrar cuán fácil es usar variables public static . Sin DialogResult , sin valores de retorno, nada. Simplemente abra la ventana, almacene sus valores con los eventos del botón en la ventana emergente, luego recupérelos luego en la función de la ventana principal.


Solo agrego un método estático para llamarlo como un 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>

Y el código detrás:

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

Entonces puedes llamarlo así:

string repeatPassword = PromptDialog.Prompt("Repeat password", "Password confirm", inputType: PromptDialog.InputType.Password);