WPF: créer une boîte de dialogue / invite

J'ai besoin de créer une boîte de dialogue / invite comprenant une zone de texte pour l'entrée de l'utilisateur. Mon problème est, comment obtenir le texte après avoir confirmé la boîte de dialogue? Habituellement, je ferais une classe pour cela qui sauvegarderait le texte dans une propriété. Cependant, je veux concevoir la boîte de dialogue en utilisant XAML. Donc, je devrais en quelque sorte étendre le Code XAML pour enregistrer le contenu de la zone de texte dans une propriété - mais je suppose que ce n'est pas possible avec du XAML pur. Quelle serait la meilleure façon de réaliser ce que j'aimerais faire? Comment construire un dialogue qui peut être défini à partir de XAML mais peut toujours retourner l'entrée? Merci pour tout indice!

66
demandé sur stefan.at.wpf 2010-05-09 07:08:13

4 réponses

La réponse" responsable "serait pour moi de suggérer de construire un ViewModel pour la boîte de dialogue et d'utiliser une liaison de données bidirectionnelle sur la zone de texte afin que le ViewModel ait une propriété" ResponseText " ou quoi d'autre. C'est assez facile à faire, mais probablement excessif.

La réponse pragmatique serait de simplement donner à votre zone de texte un x: Name afin qu'il devienne membre et expose le texte en tant que propriété dans votre code derrière la classe comme suit:

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

Puis dans votre code derrière...

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

Alors utiliser...

var dialog = new MyDialog();
if (dialog.ShowDialog() == true) {
    MessageBox.Show("You said: " + dialog.ResponseText);
}
114
répondu Josh 2013-10-28 12:20:38

J'ajoute juste une méthode statique pour l'appeler comme une 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>

Et le code derrière:

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

Donc vous pouvez l'appeler comme:

string repeatPassword = PromptDialog.Prompt("Repeat password", "Password confirm", inputType: PromptDialog.InputType.Password);
26
répondu Pythonizo 2013-07-23 13:29:25

Grande réponse de Josh, tout le crédit à lui, je l'ai légèrement modifié à ceci cependant:

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>

Code MyDialog Derrière

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

Et appelez-le Ailleurs

var dialog = new MyDialog("test", "hello");
dialog.Show();
dialog.Closing += (sender,e) =>
{
    var d = sender as MyDialog;
    if(!d.Canceled)
        MessageBox.Show(d.InputText);
}
15
répondu xtds 2016-07-14 14:11:00

Vous n'avez pas besoin de de de ces autres réponses fantaisistes. Voici un exemple simpliste qui n'a pas tous les Margin, Height, Width propriétés définies dans le XAML, mais devrait être suffisant pour montrer comment faire cela à un niveau de base.

XAML
Construire un Window page comme vous le feriez normalement et ajouter vos champs, dites - Label et TextBox contrôle à l'intérieur d'un StackPanel:

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

Créez ensuite une norme Button pour la soumission ("OK "ou" Submit") et un " Cancel" bouton si vous le souhaitez:

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

Code-Derrière
Vous ajouterez les fonctions de gestionnaire d'événements Click dans le code-behind, mais lorsque vous y allez, déclarez d'abord une variable publique où vous stockerez votre valeur de zone de texte:

public static string strUserName = String.Empty;

Ensuite, pour les fonctions du gestionnaire d'événements (cliquez avec le bouton droit sur la fonction Click sur le bouton XAML, sélectionnez "Aller à la définition", il va le créer pour vous), vous avez besoin d'une vérification pour voir si votre boîte est vide. Vous le stockez dans votre variable si ce n'est pas le cas, et fermez votre fenêtre:

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

L'Appeler Depuis Une Autre Page
Vous pensez, si je ferme ma fenêtre avec ça là-haut, ma valeur a disparu, n'est-ce pas? non!! j'ai trouvé ceci d'un autre site: http://www.dreamincode.net/forums/topic/359208-wpf-how-to-make-simple-popup-window-for-input/

Ils avaient un exemple similaire à celui-ci (je l'ai nettoyé un peu) de la façon d'ouvrir votre Window d'un autre et de récupérer le valeurs:

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

Bouton Annuler
Vous pensez, Eh bien, qu'en est-il de ce bouton Annuler, cependant? Nous ajoutons donc simplement une autre variable publique dans notre fenêtre pop-up code-behind:

public static bool cancelled = false;

Et incluons notre gestionnaire d'événements btnCancel_Click, et apportons une modification à 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.");
}

, puis que nous venons de lire cette variable dans notre MainWindow btnOpenPopup_Click événement:

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

Longue réponse, mais je voulais montrer à quel point cela est facile en utilisant des variables public static. Non DialogResult, non retourner des valeurs, rien. Ouvrez simplement la fenêtre, stockez vos valeurs avec les événements de bouton dans la fenêtre pop-up, puis récupérez-les ensuite dans la fonction de fenêtre principale.

3
répondu vapcguy 2016-11-09 21:51:32