Cuadro de diálogo de solicitud en formularios Windows Forms

115

Estoy usando System.Windows.Formspero curiosamente no tengo la capacidad para crearlos.

¿Cómo puedo obtener algo como un cuadro de diálogo de solicitud de JavaScript, sin JavaScript?

MessageBox es bueno, pero no hay forma de que el usuario ingrese una entrada.

Quiero que el usuario ingrese cualquier entrada de texto posible.

user420667
fuente
¿Puedes publicar un ejemplo de código de lo que estás intentando hacer?
Andrew Cooper
Qué tipo de entrada está buscando, proporcione más detalles. CommonDialog mira las clases que lo heredan, ¿alguna de ellas se ve bien para ti?
Sanjeevakumar Hiremath
21
Es curioso cómo tres personas le piden al OP que brinde más detalles y muestras de código, pero está bastante claro lo que quiere decir con "como un diálogo de solicitud de JavaScript" .
Camilo Martin
2
Aquí hay dos ejemplos, uno básico y otro con validación de entrada: 1. básico - csharp-examples.net/inputbox 2. validación - csharp-examples.net/inputbox-class
JasonM1

Respuestas:

274

Debe crear su propio cuadro de diálogo de solicitud. Quizás podrías crear una clase para esto.

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

Y llamándolo:

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

Actualización :

Se agregó el botón predeterminado ( tecla Intro ) y el enfoque inicial basado en comentarios y otra pregunta .

Bas
fuente
1
¿Cómo se puede extender esto a A) tener un botón de cancelación y B) validar el texto en el campo de texto de alguna manera antes de regresar?
ewok
@ewok Simplemente cree un formulario, el Diseñador de formularios lo ayudará a diseñarlo de la manera que desee.
Camilo Martin
1
@SeanWorle No veo dónde se menciona eso.
Bas
1
Lo cual logré agregando esto: prompt.AcceptButton = confirm;
B. Clay Shannon
1
Se agregó un código para manejar al usuario que cancela el mensaje con el botón de cierre y devuelve una cadena vacía
Matthew Lock
53

Agregue una referencia Microsoft.VisualBasicy use esto en su código C #:

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

Para agregar la referencia: haga clic con el botón derecho en las Referencias en la ventana del Explorador de proyectos, luego en Agregar referencia y verifique VisualBasic en esa lista.

KurvaBG
fuente
4
Esto dice Interactionque no existe en el espacio de nombresMicrosoft.VisualBasic
Khalil Khalaf
1
esto es un poco mejor que la solución de clase personalizada, ya que soporta pantallas de alta dpi
Gamache marca de
Sé que probablemente sea mejor usar la solución personalizada, pero estoy buscando una solución rápida y fácil, y esta fue la mejor. Gracias, de verdad, a todos.
Juano
14

No existe tal cosa de forma nativa en Windows Forms.

Tienes que crear tu propio formulario para eso o:

utilizar la Microsoft.VisualBasicreferencia.

Inputbox es un código heredado introducido en .Net para compatibilidad con VB6, por lo que le aconsejo que no lo haga.

Marino Šimić
fuente
2
Esto es cierto para el Microsoft.VisualBasic.Compatibilityespacio de nombres. Microsoft.VisualBasices más un conjunto de bibliotecas auxiliares sobre .Net y no es realmente específico de VB en absoluto.
Jim Wooley
-1 debido a la declaración inexacta sobre la referencia de VB. No hay razón para asustar a la gente para que no utilice esta función incorporada muy útil.
UuDdLrLrSs
6

Por lo general, no es una buena idea importar las bibliotecas de VisualBasic en programas de C # (no porque no funcionen, sino solo por compatibilidad, estilo y capacidad de actualización), pero puede llamar a Microsoft.VisualBasic.Interaction.InputBox () para mostrar el tipo de cuadro que está buscando.

Si puede crear un objeto Windows.Forms, sería mejor, pero dice que no puede hacerlo.

Sean Worle
fuente
26
¿Por qué no es una buena idea? ¿Cuáles son los posibles problemas de "compatibilidad" y "capacidad de actualización"? Estoy de acuerdo en que hablando "estilísticamente", la mayoría de los programadores de C # preferirían no usar clases de un espacio de nombres llamado VisualBasic, pero eso es solo en su cabeza. No hay realidad en ese sentimiento. También se llamaría Microsoft.MakeMyLifeEasierWithAlreadyImplementedMethodsespacio de nombres.
Cody Gray
3
En general, el paquete Microsoft.VisualBasic está destinado a simplificar la actualización del código de VB 6 únicamente. Microsoft sigue amenazando con suspender permanentemente VB (aunque esto probablemente nunca sucederá), por lo que no se garantiza el soporte futuro para este espacio de nombres. Además, se supone que una de las ventajas de .Net es la portabilidad: el mismo código se ejecutará en cualquier plataforma que tenga instalado .Net framework. Microsoft.VisualBasic, sin embargo, no se garantiza que esté disponible en ninguna otra plataforma (incluido, por lo que vale, .Net mobile, donde no está disponible en absoluto).
Sean Worle
22
Incorrecto. Ese es el Microsoft.VisualBasic.Compatibilitysub-espacio de nombres, no todo. En el Microsoft.VisualBasicespacio de nombres se incluyen muchas funciones "básicas" ; no va a ninguna parte. Microsoft ha amenazado con "suspender" VB 6, no VB.NET. Han prometido repetidamente que no irá a ninguna parte. Algunas personas todavía no parecen haber descubierto la diferencia ...
Cody Gray
4

Otra forma de hacer esto: suponiendo que tenga un tipo de entrada TextBox, cree un formulario y tenga el valor del cuadro de texto como una propiedad pública.

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

En el formulario principal, este será el código:

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

;

De esta manera, el código se ve más limpio:

  1. Si se agrega lógica de validación.
  2. Si se agregan varios otros tipos de entrada.
usuario2347528
fuente
4

La respuesta de Bas puede causarle problemas de memoria teóricamente, ya que ShowDialog no se eliminará. Creo que esta es una forma más adecuada. También mencione que textLabel es legible con texto más largo.

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

Implementación:

using(Prompt prompt = new Prompt("text", "caption")){
    string result = prompt.Result;
}
Gideon Mulder
fuente
2
Buen uso de la gestión de la memoria. Pero esto falla al agregar un botón de cancelación porque promptes nulo en ese punto. Una solución simple para permitir la cancelación del mensaje es reemplazar prompt.Dispose();dentro de public void Dispose()conif (prompt != null) { prompt.Dispose(); }
Marcus Parsons
3

Basado en el trabajo de Bas Brekelmans anterior, también he creado dos derivaciones -> cuadros de diálogo de "entrada" que le permiten recibir del usuario tanto un valor de texto como un booleano (TextBox y 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());
    }
}

... y texto junto con una selección de una de las múltiples opciones (TextBox y 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());
    }
}

Ambos requieren los mismos usos:

using System;
using System.Windows.Forms;

Llámalos así:

Llámalos así:

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
fuente
2

La respuesta de Bas Brekelmans es muy elegante en su simplicidad. Pero descubrí que para una aplicación real se necesita un poco más, como:

  • Crezca de forma adecuada cuando el texto del mensaje sea demasiado largo.
  • No aparece automáticamente en medio de la pantalla.
  • No proporciona ninguna validación de la entrada del usuario.

La clase aquí maneja estas limitaciones: http://www.codeproject.com/Articles/31315/Getting-User-Input-With-Dialogs-Part-1

Acabo de descargar la fuente y copié InputBox.cs en mi proyecto.

Sin embargo, me sorprende que no haya algo mejor ... Mi única queja real es que el texto de los subtítulos no admite nuevas líneas ya que usa un control de etiqueta.

blak3r
fuente
Buena respuesta, pero fuera del alcance de la pregunta formulada
Munim Munna
1

Desafortunadamente, C # todavía no ofrece esta capacidad en las bibliotecas integradas. La mejor solución en la actualidad es crear una clase personalizada con un método que muestre un formulario pequeño. Si está trabajando en Visual Studio, puede hacer esto haciendo clic en Proyecto> Agregar clase

Agregar clase

Elementos de Visual C #> código> clase Agregar clase 2

Nombre la clase PopUpBox (puede cambiarle el nombre más tarde si lo desea) y pegue el siguiente código:

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

Deberá cambiar el espacio de nombres a lo que esté usando. El método devuelve una cadena, así que aquí tienes un ejemplo de cómo implementarlo en tu método de llamada:

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

Este método comprueba la cadena devuelta en busca de un valor de texto, cadena vacía o "cancelar" (el método getUserInput devuelve "cancelar" si se hace clic en el botón cancelar) y actúa en consecuencia. Si el usuario no ingresó nada y hizo clic en Aceptar, le dirá al usuario y le preguntará si desea cancelar o volver a ingresar su texto.

Notas de publicación: En mi propia implementación, encontré que a todas las otras respuestas les faltaba 1 o más de las siguientes:

  • Un botón de cancelar
  • La capacidad de contener símbolos en la cadena enviada al método.
  • Cómo acceder al método y manejar el valor devuelto.

Por lo tanto, he publicado mi propia solución. Espero que alguien lo encuentre útil. Gracias a los comentaristas de Bas y Gideon + por sus contribuciones, ¡me ayudaron a encontrar una solución viable!

technoman23
fuente
0

aquí está mi versión refactorizada que acepta multilínea / única como opción

   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
fuente
-2

Aquí hay un ejemplo en 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
fuente