Boîte de dialogue d'invite dans Windows Forms

115

J'utilise System.Windows.Formsmais étrangement je n'ai pas la capacité de les créer.

Comment puis-je obtenir quelque chose comme une boîte de dialogue d'invite javascript, sans javascript?

MessageBox est sympa, mais il n'y a aucun moyen pour l'utilisateur d'entrer une entrée.

Je veux que l'utilisateur entre toute saisie de texte possible.

user420667
la source
Pouvez-vous publier un exemple de code de ce que vous essayez de faire?
Andrew Cooper
Quel type de contribution recherchez-vous, donnez un peu plus de détails. CommonDialog regarde les classes qui en héritent, est-ce que l'une d'elles vous convient?
Sanjeevakumar Hiremath
21
C'est drôle comment trois personnes demandent à l'OP de donner plus de détails et d'exemples de code, mais ce qu'il entend par "comme une boîte de dialogue d'invite javascript" est assez clair .
Camilo Martin
2
Voici deux exemples, l'un basique et l'autre avec validation d'entrée: 1. basique - csharp-examples.net/inputbox 2. validation - csharp-examples.net/inputbox-class
JasonM1

Réponses:

274

Vous devez créer votre propre boîte de dialogue d'invite. Vous pourriez peut-être créer une classe pour cela.

public static class Prompt
{
    public static string ShowDialog(string text, string caption)
    {
        Form prompt = new Form()
        {
            Width = 500,
            Height = 150,
            FormBorderStyle = FormBorderStyle.FixedDialog,
            Text = caption,
            StartPosition = FormStartPosition.CenterScreen
        };
        Label textLabel = new Label() { Left = 50, Top=20, Text=text };
        TextBox textBox = new TextBox() { Left = 50, Top=50, Width=400 };
        Button confirmation = new Button() { Text = "Ok", Left=350, Width=100, Top=70, DialogResult = DialogResult.OK };
        confirmation.Click += (sender, e) => { prompt.Close(); };
        prompt.Controls.Add(textBox);
        prompt.Controls.Add(confirmation);
        prompt.Controls.Add(textLabel);
        prompt.AcceptButton = confirmation;

        return prompt.ShowDialog() == DialogResult.OK ? textBox.Text : "";
    }
}

Et l'appelant:

string promptValue = Prompt.ShowDialog("Test", "123");

Mise à jour :

Ajout du bouton par défaut (touche d' entrée ) et de la mise au point initiale basée sur les commentaires et une autre question .

Bas
la source
1
Comment étendre cela à A) avoir un bouton d'annulation et B) valider le texte dans le champ de texte d'une manière ou d'une autre avant de revenir?
ewok le
@ewok Créez simplement un formulaire, le Concepteur de formulaires vous aidera à le présenter comme vous le souhaitez.
Camilo Martin
1
@SeanWorle Je ne vois pas où cela est mentionné.
Bas
1
Ce que j'ai accompli en ajoutant ceci: prompt.AcceptButton = confirmation;
B. Clay Shannon
1
Ajout d'un code pour gérer l'utilisateur annulant l'invite avec le bouton de fermeture et renvoyant une chaîne vide
Matthew Lock
53

Ajoutez une référence Microsoft.VisualBasicet utilisez-la dans votre code C #:

string input = Microsoft.VisualBasic.Interaction.InputBox("Prompt", 
                       "Title", 
                       "Default", 
                       0, 
                       0);

Pour ajouter la référence: faites un clic droit sur les références dans votre fenêtre Explorateur de projet puis sur Ajouter une référence, et vérifiez VisualBasic dans cette liste.

KurvaBG
la source
4
Cela dit Interactionn'existe pas dans l'espace de nomsMicrosoft.VisualBasic
Khalil Khalaf
1
c'est légèrement mieux que la solution de classe personnalisée car elle prend en charge les écrans haute résolution
marquez gamache
Je sais que l'utilisation de la solution personnalisée serait probablement meilleure, mais je recherche une solution rapide et facile, et c'était la meilleure. Merci vraiment à tous.
Juano le
14

Une telle chose n'existe pas nativement dans Windows Forms.

Vous devez créer votre propre formulaire pour cela ou:

utilisez la Microsoft.VisualBasicréférence.

Inputbox est un code hérité introduit dans .Net pour la compatibilité VB6 - je vous conseille donc de ne pas le faire.

Marino Šimić
la source
2
Cela est vrai pour l' Microsoft.VisualBasic.Compatibilityespace de noms. Microsoft.VisualBasicest plus un ensemble de bibliothèques d'aide au-dessus de .Net et n'est pas vraiment spécifique à VB.
Jim Wooley
-1 à cause de la déclaration inexacte concernant la référence VB. Aucune raison de dissuader les gens d'utiliser cette fonctionnalité intégrée très utile.
UuDdLrLrSs
6

Ce n'est généralement pas une très bonne idée d'importer les bibliothèques VisualBasic dans des programmes C # (non pas parce qu'elles ne fonctionnent pas, mais juste pour la compatibilité, le style et la capacité de mise à niveau), mais vous pouvez appeler Microsoft.VisualBasic.Interaction.InputBox () pour afficher le type de boîte que vous recherchez.

Si vous pouvez créer un objet Windows.Forms, ce serait mieux, mais vous dites que vous ne pouvez pas le faire.

Sean Worle
la source
26
Pourquoi n'est-ce pas une bonne idée? Quels sont les problèmes de «compatibilité» et de «capacité de mise à niveau» possibles? Je conviens que "stylistiquement", la plupart des programmeurs C # préféreraient ne pas utiliser les classes d'un espace de noms appelé VisualBasic, mais ce n'est que dans leur tête. Il n'y a pas de réalité à ce sentiment. Il serait tout aussi bien appelé l' Microsoft.MakeMyLifeEasierWithAlreadyImplementedMethodsespace de noms.
Cody Gray
3
En général, le package Microsoft.VisualBasic est destiné à simplifier la mise à niveau du code à partir de VB 6 uniquement. Microsoft continue de menacer de suspendre définitivement VB (bien que cela ne se produise probablement jamais), donc la prise en charge future de cet espace de noms n'est pas garantie. De plus, l'un des avantages de .Net est censé être la portabilité - le même code fonctionnera sur n'importe quelle plate-forme sur laquelle le framework .Net est installé. Microsoft.VisualBasic, cependant, n'est pas garanti d'être disponible sur aucune autre plate-forme (y compris, pour ce que ça vaut, .Net mobile, où il n'est pas disponible du tout).
Sean Worle
22
Incorrect. C'est le Microsoft.VisualBasic.Compatibilitysous-espace de noms, pas le tout. De nombreuses fonctionnalités "principales" sont incluses dans l' Microsoft.VisualBasicespace de noms; ça ne va nulle part. Microsoft a menacé de "suspendre" VB 6, pas VB.NET. Ils ont promis à maintes reprises que cela ne mènerait nulle part. Certaines personnes ne semblent toujours pas avoir compris la différence ...
Cody Gray
4

Autre façon de procéder: en supposant que vous avez un type d'entrée TextBox, créez un formulaire et que la valeur de la zone de texte est une propriété publique.

public partial class TextPrompt : Form
{
    public string Value
    {
        get { return tbText.Text.Trim(); }
    }

    public TextPrompt(string promptInstructions)
    {
        InitializeComponent();

        lblPromptText.Text = promptInstructions;
    }

    private void BtnSubmitText_Click(object sender, EventArgs e)
    {
        Close();
    }

    private void TextPrompt_Load(object sender, EventArgs e)
    {
        CenterToParent();
    }
}

Dans le formulaire principal, ce sera le code:

var t = new TextPrompt(this, "Type the name of the settings file:");
t.ShowDialog()

;

De cette façon, le code semble plus propre:

  1. Si une logique de validation est ajoutée.
  2. Si divers autres types d'entrée sont ajoutés.
user2347528
la source
4

La réponse de Bas peut vous mettre en mémoire, théoriquement, puisque ShowDialog ne sera pas supprimé. Je pense que c'est une manière plus appropriée. Mentionner également que textLabel est lisible avec un texte plus long.

public class Prompt : IDisposable
{
    private Form prompt { get; set; }
    public string Result { get; }

    public Prompt(string text, string caption)
    {
        Result = ShowDialog(text, caption);
    }
    //use a using statement
    private string ShowDialog(string text, string caption)
    {
        prompt = new Form()
        {
            Width = 500,
            Height = 150,
            FormBorderStyle = FormBorderStyle.FixedDialog,
            Text = caption,
            StartPosition = FormStartPosition.CenterScreen,
            TopMost = true
        };
        Label textLabel = new Label() { Left = 50, Top = 20, Text = text, Dock = DockStyle.Top, TextAlign = ContentAlignment.MiddleCenter };
        TextBox textBox = new TextBox() { Left = 50, Top = 50, Width = 400 };
        Button confirmation = new Button() { Text = "Ok", Left = 350, Width = 100, Top = 70, DialogResult = DialogResult.OK };
        confirmation.Click += (sender, e) => { prompt.Close(); };
        prompt.Controls.Add(textBox);
        prompt.Controls.Add(confirmation);
        prompt.Controls.Add(textLabel);
        prompt.AcceptButton = confirmation;

        return prompt.ShowDialog() == DialogResult.OK ? textBox.Text : "";
    }

    public void Dispose()
    {
        //See Marcus comment
        if (prompt != null) { 
            prompt.Dispose(); 
        }
    }
}

La mise en oeuvre:

using(Prompt prompt = new Prompt("text", "caption")){
    string result = prompt.Result;
}
Gideon Mulder
la source
2
Bonne utilisation de la gestion de la mémoire. Mais cela échoue lors de l'ajout d'un bouton d'annulation car le promptest nul à ce stade. Une solution simple pour permettre l'annulation de l'invite consiste à remplacer l' prompt.Dispose();intérieur de public void Dispose()parif (prompt != null) { prompt.Dispose(); }
Marcus Parsons
3

Sur la base du travail de Bas Brekelmans ci-dessus, j'ai également créé deux dérivations -> dialogues "input" qui vous permettent de recevoir de l'utilisateur à la fois une valeur textuelle et un booléen (TextBox et CheckBox):

public static class PromptForTextAndBoolean
{
    public static string ShowDialog(string caption, string text, string boolStr)
    {
        Form prompt = new Form();
        prompt.Width = 280;
        prompt.Height = 160;
        prompt.Text = caption;
        Label textLabel = new Label() { Left = 16, Top = 20, Width = 240, Text = text };
        TextBox textBox = new TextBox() { Left = 16, Top = 40, Width = 240, TabIndex = 0, TabStop = true };
        CheckBox ckbx = new CheckBox() { Left = 16, Top = 60, Width = 240, Text = boolStr };
        Button confirmation = new Button() { Text = "Okay!", Left = 16, Width = 80, Top = 88, TabIndex = 1, TabStop = true };
        confirmation.Click += (sender, e) => { prompt.Close(); };
        prompt.Controls.Add(textLabel);
        prompt.Controls.Add(textBox);
        prompt.Controls.Add(ckbx);
        prompt.Controls.Add(confirmation);
        prompt.AcceptButton = confirmation;
        prompt.StartPosition = FormStartPosition.CenterScreen;
        prompt.ShowDialog();
        return string.Format("{0};{1}", textBox.Text, ckbx.Checked.ToString());
    }
}

... et du texte avec une sélection de l'une des multiples options (TextBox et ComboBox):

public static class PromptForTextAndSelection
{
    public static string ShowDialog(string caption, string text, string selStr)
    {
        Form prompt = new Form();
        prompt.Width = 280;
        prompt.Height = 160;
        prompt.Text = caption;
        Label textLabel = new Label() { Left = 16, Top = 20, Width = 240, Text = text };
        TextBox textBox = new TextBox() { Left = 16, Top = 40, Width = 240, TabIndex = 0, TabStop = true };
        Label selLabel = new Label() { Left = 16, Top = 66, Width = 88, Text = selStr };
        ComboBox cmbx = new ComboBox() { Left = 112, Top = 64, Width = 144 };
        cmbx.Items.Add("Dark Grey");
        cmbx.Items.Add("Orange");
        cmbx.Items.Add("None");
        Button confirmation = new Button() { Text = "In Ordnung!", Left = 16, Width = 80, Top = 88, TabIndex = 1, TabStop = true };
        confirmation.Click += (sender, e) => { prompt.Close(); };
        prompt.Controls.Add(textLabel);
        prompt.Controls.Add(textBox);
        prompt.Controls.Add(selLabel);
        prompt.Controls.Add(cmbx);
        prompt.Controls.Add(confirmation);
        prompt.AcceptButton = confirmation;
        prompt.StartPosition = FormStartPosition.CenterScreen;
        prompt.ShowDialog();
        return string.Format("{0};{1}", textBox.Text, cmbx.SelectedItem.ToString());
    }
}

Les deux nécessitent les mêmes utilisations:

using System;
using System.Windows.Forms;

Appelez-les comme ça:

Appelez-les comme ça:

PromptForTextAndBoolean.ShowDialog("Jazz", "What text should accompany the checkbox?", "Allow Scat Singing"); 

PromptForTextAndSelection.ShowDialog("Rock", "What should the name of the band be?", "Beret color to wear");
B. Clay Shannon
la source
2

La réponse de Bas Brekelmans est très élégante dans sa simplicité. Mais, j'ai trouvé que pour une application réelle, un peu plus était nécessaire, comme:

  • Développez la forme de manière appropriée lorsque le texte du message est trop long.
  • Ne s'affiche pas automatiquement au milieu de l'écran.
  • Ne fournit aucune validation de l'entrée utilisateur.

La classe ici gère ces limitations: http://www.codeproject.com/Articles/31315/Getting-User-Input-With-Dialogs-Part-1

Je viens de télécharger la source et copié InputBox.cs dans mon projet.

Surpris qu'il n'y ait pas quelque chose d'encore mieux cependant ... Ma seule vraie plainte est que le texte de légende ne prend pas en charge les nouvelles lignes car il utilise un contrôle d'étiquette.

blak3r
la source
Bonne réponse, mais hors du cadre de la question posée
Munim Munna
1

Malheureusement, C # n'offre toujours pas cette capacité dans les bibliothèques intégrées. La meilleure solution à l'heure actuelle est de créer une classe personnalisée avec une méthode qui affiche un petit formulaire. Si vous travaillez dans Visual Studio, vous pouvez le faire en cliquant sur Projet> Ajouter une classe

Ajouter une classe

Visual C # items> code> classe Ajouter la classe 2

Nommez la classe PopUpBox (vous pouvez la renommer plus tard si vous le souhaitez) et collez le code suivant:

using System.Drawing;
using System.Windows.Forms;

namespace yourNameSpaceHere
{
    public class PopUpBox
    {
        private static Form prompt { get; set; }

        public static string GetUserInput(string instructions, string caption)
        {
            string sUserInput = "";
            prompt = new Form() //create a new form at run time
            {
                Width = 500, Height = 150, FormBorderStyle = FormBorderStyle.FixedDialog, Text = caption,
                StartPosition = FormStartPosition.CenterScreen, TopMost = true
            };
            //create a label for the form which will have instructions for user input
            Label lblTitle = new Label() { Left = 50, Top = 20, Text = instructions, Dock = DockStyle.Top, TextAlign = ContentAlignment.TopCenter };
            TextBox txtTextInput = new TextBox() { Left = 50, Top = 50, Width = 400 };

            ////////////////////////////OK button
            Button btnOK = new Button() { Text = "OK", Left = 250, Width = 100, Top = 70, DialogResult = DialogResult.OK };
            btnOK.Click += (sender, e) => 
            {
                sUserInput = txtTextInput.Text;
                prompt.Close();
            };
            prompt.Controls.Add(txtTextInput);
            prompt.Controls.Add(btnOK);
            prompt.Controls.Add(lblTitle);
            prompt.AcceptButton = btnOK;
            ///////////////////////////////////////

            //////////////////////////Cancel button
            Button btnCancel = new Button() { Text = "Cancel", Left = 350, Width = 100, Top = 70, DialogResult = DialogResult.Cancel };
            btnCancel.Click += (sender, e) => 
            {
                sUserInput = "cancel";
                prompt.Close();
            };
            prompt.Controls.Add(btnCancel);
            prompt.CancelButton = btnCancel;
            ///////////////////////////////////////

            prompt.ShowDialog();
            return sUserInput;
        }

        public void Dispose()
        {prompt.Dispose();}
    }
}

Vous devrez changer l'espace de noms pour celui que vous utilisez. La méthode renvoie une chaîne, voici donc un exemple de la façon de l'implémenter dans votre méthode d'appel:

bool boolTryAgain = false;

do
{
    string sTextFromUser = PopUpBox.GetUserInput("Enter your text below:", "Dialog box title");
    if (sTextFromUser == "")
    {
        DialogResult dialogResult = MessageBox.Show("You did not enter anything. Try again?", "Error", MessageBoxButtons.YesNo);
        if (dialogResult == DialogResult.Yes)
        {
            boolTryAgain = true; //will reopen the dialog for user to input text again
        }
        else if (dialogResult == DialogResult.No)
        {
            //exit/cancel
            MessageBox.Show("operation cancelled");
            boolTryAgain = false;
        }//end if
    }
    else
    {
        if (sTextFromUser == "cancel")
        {
            MessageBox.Show("operation cancelled");
        }
        else
        {
            MessageBox.Show("Here is the text you entered: '" + sTextFromUser + "'");
            //do something here with the user input
        }

    }
} while (boolTryAgain == true);

Cette méthode vérifie la chaîne renvoyée pour une valeur de texte, une chaîne vide ou "annuler" (la méthode getUserInput renvoie "annuler" si le bouton d'annulation est cliqué) et agit en conséquence. Si l'utilisateur n'a rien entré et a cliqué sur OK, il le dira à l'utilisateur et lui demandera s'il souhaite annuler ou ressaisir son texte.

Notes de publication: Dans ma propre implémentation, j'ai constaté que toutes les autres réponses manquaient 1 ou plusieurs des éléments suivants:

  • Un bouton d'annulation
  • La possibilité de contenir des symboles dans la chaîne envoyée à la méthode
  • Comment accéder à la méthode et gérer la valeur renvoyée.

Ainsi, j'ai publié ma propre solution. J'espère que quelqu'un le trouvera utile. Merci à Bas et Gideon + commentateurs pour vos contributions, vous m'avez aidé à trouver une solution réalisable!

technoman23
la source
0

voici ma version refactorisée qui accepte les multilignes / single en option

   public string ShowDialog(string text, string caption, bool isMultiline = false, int formWidth = 300, int formHeight = 200)
        {
            var prompt = new Form
            {
                Width = formWidth,
                Height = isMultiline ? formHeight : formHeight - 70,
                FormBorderStyle = isMultiline ? FormBorderStyle.Sizable : FormBorderStyle.FixedSingle,
                Text = caption,
                StartPosition = FormStartPosition.CenterScreen,
                MaximizeBox = isMultiline
            };

            var textLabel = new Label
            {
                Left = 10,
                Padding = new Padding(0, 3, 0, 0),
                Text = text,
                Dock = DockStyle.Top
            };

            var textBox = new TextBox
            {
                Left = isMultiline ? 50 : 4,
                Top = isMultiline ? 50 : textLabel.Height + 4,
                Multiline = isMultiline,
                Dock = isMultiline ? DockStyle.Fill : DockStyle.None,
                Width = prompt.Width - 24,
                Anchor = isMultiline ? AnchorStyles.Left | AnchorStyles.Top : AnchorStyles.Left | AnchorStyles.Right
            };

            var confirmationButton = new Button
            {
                Text = @"OK",
                Cursor = Cursors.Hand,
                DialogResult = DialogResult.OK,
                Dock = DockStyle.Bottom,
            };

            confirmationButton.Click += (sender, e) =>
            {
                prompt.Close();
            };

            prompt.Controls.Add(textBox);
            prompt.Controls.Add(confirmationButton);
            prompt.Controls.Add(textLabel);

            return prompt.ShowDialog() == DialogResult.OK ? textBox.Text : string.Empty;
        }
Alper Ebicoglu
la source
-2

Voici un exemple dans VB.NET

Public Function ShowtheDialog(caption As String, text As String, selStr As String) As String
    Dim prompt As New Form()
    prompt.Width = 280
    prompt.Height = 160
    prompt.Text = caption
    Dim textLabel As New Label() With { _
         .Left = 16, _
         .Top = 20, _
         .Width = 240, _
         .Text = text _
    }
    Dim textBox As New TextBox() With { _
         .Left = 16, _
         .Top = 40, _
         .Width = 240, _
         .TabIndex = 0, _
         .TabStop = True _
    }
    Dim selLabel As New Label() With { _
         .Left = 16, _
         .Top = 66, _
         .Width = 88, _
         .Text = selStr _
    }
    Dim cmbx As New ComboBox() With { _
         .Left = 112, _
         .Top = 64, _
         .Width = 144 _
    }
    cmbx.Items.Add("Dark Grey")
    cmbx.Items.Add("Orange")
    cmbx.Items.Add("None")
    cmbx.SelectedIndex = 0
    Dim confirmation As New Button() With { _
         .Text = "In Ordnung!", _
         .Left = 16, _
         .Width = 80, _
         .Top = 88, _
         .TabIndex = 1, _
         .TabStop = True _
    }
    AddHandler confirmation.Click, Sub(sender, e) prompt.Close()
    prompt.Controls.Add(textLabel)
    prompt.Controls.Add(textBox)
    prompt.Controls.Add(selLabel)
    prompt.Controls.Add(cmbx)
    prompt.Controls.Add(confirmation)
    prompt.AcceptButton = confirmation
    prompt.StartPosition = FormStartPosition.CenterScreen
    prompt.ShowDialog()
    Return String.Format("{0};{1}", textBox.Text, cmbx.SelectedItem.ToString())
End Function
user890332
la source