Диалог подсказки в Windows Forms


115

Я использую, System.Windows.Formsно, как ни странно, не имею возможности их создавать.

Как я могу получить что-то вроде диалогового окна с приглашением javascript без javascript?

MessageBox - это хорошо, но пользователь не может вводить данные.

Я хочу, чтобы пользователь вводил любой возможный текст.


Можете ли вы опубликовать пример кода того, что вы пытаетесь сделать?
Эндрю Купер

Какую информацию вы ищете, опишите подробнее. CommonDialog посмотрите на наследующие его классы, вам подходит какой-нибудь из них?
Sanjeevakumar Hiremath,

21
Забавно, как три человека просят ОП предоставить более подробную информацию и образцы кода, но довольно ясно, что он имеет в виду, говоря «как диалоговое окно с приглашением javascript» .
Камило Мартин

2
Вот два примера, один базовый, а другой с проверкой ввода: 1. базовый - csharp-examples.net/inputbox 2. проверка - csharp-examples.net/inputbox-class
JasonM1

Ответы:


274

Вам нужно создать свой собственный диалог подсказки. Возможно, вы могли бы создать для этого класс.

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

И называя это:

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

Обновление :

Добавлена ​​кнопка по умолчанию ( клавиша ввода ) и начальный фокус на основе комментариев и другого вопроса .


1
Как бы это можно было расширить до A) иметь кнопку отмены и B) каким-либо образом проверить текст в текстовом поле перед возвратом?
ewok

@ewok Просто создайте форму, конструктор форм поможет вам оформить ее так, как вы хотите.
Камило Мартин

1
@SeanWorle Я не понимаю, где это упоминается.
Bas

1
Я добился этого, добавив следующее: prompt.AcceptButton = confirm;
Б. Клей Шеннон

1
Добавлен код для обработки пользователем отмены приглашения с помощью кнопки закрытия и возврата пустой строки
Мэтью Лок,

53

Добавьте ссылку Microsoft.VisualBasicи используйте ее в своем коде C #:

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

Чтобы добавить ссылку: щелкните правой кнопкой мыши ссылки в окне обозревателя проектов, затем выберите Добавить ссылку и выберите VisualBasic из этого списка.


4
Это говорит о том, Interactionчто не существует в пространстве именMicrosoft.VisualBasic
Халил Халаф

1
это немного лучше, чем решение нестандартного класса, поскольку оно поддерживает экраны с высоким разрешением
Марк Гамаш,

Я знаю, что, вероятно, было бы лучше использовать индивидуальное решение, но я ищу быстрое и простое решение, и это было лучшим. Спасибо, правда, всем.
Хуано,

14

В Windows Forms такого нет.

Для этого вам необходимо создать свою собственную форму или:

использовать Microsoft.VisualBasic ссылку.

Inputbox - это устаревший код, перенесенный в .Net для совместимости с VB6, поэтому я советую этого не делать.


2
Это верно для Microsoft.VisualBasic.Compatibilityпространства имен. Microsoft.VisualBasicэто скорее набор вспомогательных библиотек поверх .Net и вообще не специфичен для VB.
Джим Вули

-1 из-за неточного заявления о ссылке на VB. Нет причин отпугивать людей от использования этой очень полезной встроенной функции.
UuDdLrLrSs

6

Как правило, не рекомендуется импортировать библиотеки VisualBasic в программы C # (не потому, что они не работают, а только для совместимости, стиля и возможности обновления), но вы можете вызвать Microsoft.VisualBasic.Interaction.InputBox () для отображения нужного вам окна.

Если вы можете создать объект Windows.Forms, это будет лучше всего, но вы говорите, что не можете этого сделать.


26
Почему это плохая идея? Каковы возможные проблемы "совместимости" и "возможности обновления"? Я согласен с тем, что «стилистически» большинство программистов на C # предпочли бы не использовать классы из названного пространства имен VisualBasic, но это только в их голове. В этом чувстве нет реальности. Его также можно было бы назвать Microsoft.MakeMyLifeEasierWithAlreadyImplementedMethodsпространством имен.
Коди Грей

3
В общем, пакет Microsoft.VisualBasic предназначен для упрощения обновления кода только с VB 6. Microsoft продолжает угрожать окончательно закрыть VB (хотя этого, вероятно, никогда не произойдет), поэтому будущая поддержка этого пространства имен не гарантируется. Кроме того, одним из преимуществ .Net должна быть переносимость - один и тот же код будет работать на любой платформе, на которой установлена ​​платформа .Net. Однако не гарантируется, что Microsoft.VisualBasic будет доступен на какой-либо другой платформе (в том числе, если это стоит, на .Net Mobile, где он вообще недоступен).
Sean Worle

22
Неправильно. Это Microsoft.VisualBasic.Compatibilityподпространство имен, а не все. В Microsoft.VisualBasicпространство имен включено множество «основных» функций ; это никуда не денется. Microsoft пригрозила «закатом» VB 6, а не VB.NET. Они неоднократно обещали, что это никуда не денется. Некоторые люди, кажется, до сих пор не поняли разницу ...
Коди Грей

4

Другой способ сделать это: если у вас есть тип ввода TextBox, создать форму и значение текстового поля как общедоступное свойство.

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

В основной форме это будет код:

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

;

Таким образом код выглядит чище:

  1. Если добавлена ​​логика проверки.
  2. Если добавлены различные другие типы ввода.

4

Ответ Баса теоретически может вызвать у вас проблемы с памятью, поскольку ShowDialog не будет удален. Думаю, это более правильный способ. Также укажите, что textLabel читается с более длинным текстом.

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

Реализация:

using(Prompt prompt = new Prompt("text", "caption")){
    string result = prompt.Result;
}

2
Хорошее использование управления памятью. Но это не удается при добавлении кнопки отмены, потому что promptв этот момент значение null. Простое исправление, позволяющее отменить приглашение, - заменить prompt.Dispose();внутреннюю часть public void Dispose()наif (prompt != null) { prompt.Dispose(); }
Маркус Парсонс

3

Основываясь на работе Баса Брекельмана, приведенной выше, я также создал две производные -> диалоговые окна «ввода», которые позволяют получать от пользователя как текстовое значение, так и логическое значение (TextBox и 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());
    }
}

... и текст вместе с выбором одного из нескольких вариантов (TextBox и 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());
    }
}

Оба требуют одинакового использования:

using System;
using System.Windows.Forms;

Назовите их так:

Назовите их так:

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

2

Ответ Баса Брекельмана очень элегантен в своей простоте. Но я обнаружил, что для реального приложения требуется немного больше, например:

  • Если текст сообщения слишком длинный, увеличивайте форму соответствующим образом.
  • Не всплывает автоматически в середине экрана.
  • Не обеспечивает никакой проверки пользовательского ввода.

Класс здесь обрабатывает эти ограничения: http://www.codeproject.com/Articles/31315/Getting-User-Input-With-Dialogs-Part-1

Я только что загрузил исходный код и скопировал InputBox.cs в свой проект.

Удивлен, что нет ничего лучше ... Моя единственная реальная жалоба заключается в том, что текст заголовка не поддерживает в нем символы новой строки, поскольку он использует элемент управления меткой.


Хороший ответ, но выходит за рамки
заданного

1

К сожалению, C # до сих пор не предлагает эту возможность во встроенных библиотеках. Лучшее решение в настоящее время - создать собственный класс с методом, выводящим небольшую форму. Если вы работаете в Visual Studio, вы можете сделать это, нажав Проект> Добавить класс.

Добавить класс

Элементы Visual C #> код> класс Добавить класс 2

Назовите класс PopUpBox (вы можете переименовать его позже, если хотите) и вставьте следующий код:

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

Вам нужно будет изменить пространство имен на то, что вы используете. Метод возвращает строку, поэтому вот пример того, как реализовать его в вызывающем методе:

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

Этот метод проверяет возвращаемую строку на наличие текстового значения, пустой строки или «отменить» (метод getUserInput возвращает «отменить», если нажата кнопка отмены) и действует соответственно. Если пользователь ничего не ввел и нажал «ОК», он сообщит пользователю и спросит, хотят ли они отменить или повторно ввести свой текст.

Примечания к публикациям: в моей собственной реализации я обнаружил, что во всех других ответах не хватало одного или нескольких из следующих пунктов:

  • Кнопка отмены
  • Возможность содержать символы в строке, отправляемой в метод
  • Как получить доступ к методу и обработать возвращаемое значение.

Таким образом, я опубликовал собственное решение. Надеюсь, кому-то это пригодится. Благодарим Баса и Гидеона + комментаторов за ваш вклад, вы помогли мне найти работоспособное решение!


0

вот моя отредактированная версия, которая принимает многострочный / одинарный вариант

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

-2

Вот пример на 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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.