【问题标题】:Prompt Dialog in Windows FormsWindows 窗体中的提示对话框
【发布时间】:2011-07-22 13:43:30
【问题描述】:

我正在使用System.Windows.Forms,但奇怪的是没有能力创建它们。

如何在没有 javascript 的情况下获得类似 javascript 提示对话框的内容?

MessageBox 不错,但用户无法输入。

我希望用户输入任何可能的文本输入。

【问题讨论】:

  • 你能发布一个你想要做什么的代码示例吗?
  • 您在寻找什么样的输入,请提供更多细节。 CommonDialog 看看继承它的类,它们中的任何一个看起来都适合你吗?
  • 有趣的是,三个人要求 OP 提供更多细节和代码示例,但很清楚他所说的“就像一个 javascript 提示对话框” 是什么意思。
  • 这里有两个示例,一个是基本的,另一个是输入验证:1. 基本 - csharp-examples.net/inputbox 2. 验证 - csharp-examples.net/inputbox-class

标签: c# .net winforms dialog prompt


【解决方案1】:

您需要创建自己的提示对话框。您也许可以为此创建一个类。

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

更新

添加了默认按钮(回车键)和基于 cmets 和 another question 的初始焦点。

【讨论】:

  • 如何将其扩展到 A)有一个取消按钮和 B)在返回之前以某种方式验证文本字段中的文本?
  • @ewok 只需创建一个表单,表单设计器将帮助您按照您想要的方式进行布局。
  • @SeanWorle 我看不出在哪里提到。
  • 我通过添加这个来完成:prompt.AcceptButton = Confirm;
  • 添加了处理用户使用关闭按钮取消提示并返回空字符串的代码
【解决方案2】:

添加对 Microsoft.VisualBasic 的引用并将其用于您的 C# 代码:

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

要添加引用:右键单击项目资源管理器窗口中的引用,然后单击添加引用,然后从该列表中选中 VisualBasic。

【讨论】:

  • 这表示Interaction 不存在于命名空间Microsoft.VisualBasic
  • 这比自定义类解决方案略好,因为它支持高 dpi 屏幕
  • 我知道使用自定义解决方案可能会更好,但我正在寻找一种快速简便的解决方案,这是最好的。真的,谢谢大家。
【解决方案3】:

Windows 窗体中没有这种东西。

您必须为此创建自己的表单,或者:

使用Microsoft.VisualBasic 引用。

Inputbox 是引入 .Net 以兼容 VB6 的遗留代码 - 所以我建议不要这样做。

【讨论】:

  • Microsoft.VisualBasic.Compatibility 命名空间是这样。 Microsoft.VisualBasic 更多的是 .Net 之上的一组帮助程序库,根本不是 VB 特定的。
  • -1,因为关于 VB 参考的陈述不准确。没有理由吓唬人们不要使用这个非常有用的内置功能。
【解决方案4】:

将 VisualBasic 库导入 C# 程序通常不是一个好主意(不是因为它们不起作用,而是为了兼容性、样式和升级能力),但您可以调用 Microsoft.VisualBasic.Interaction。 InputBox() 显示您要查找的框类型。

如果您可以创建一个 Windows.Forms 对象,那将是最好的,但您说您不能这样做。

【讨论】:

  • 为什么这不是一个好主意?可能的“兼容性”和“升级能力”问题是什么?我同意“风格上”的说法,大多数 C# 程序员宁愿不使用名为 VisualBasic 的命名空间中的类,但这只是他们的想法。这种感觉是不真实的。它也可以称为 Microsoft.MakeMyLifeEasierWithAlreadyImplementedMethods 命名空间。
  • 一般来说,Microsoft.VisualBasic 包仅用于简化从 VB 6 升级代码的过程。 Microsoft 一直威胁要永久停用 VB(尽管这可能永远不会真正发生),因此不能保证将来对这个命名空间的支持。此外,.Net 的优势之一应该是可移植性——相同的代码将在任何安装了 .Net 框架的平台上运行。但是,不保证 Microsoft.VisualBasic 可在任何其他平台上使用(包括,就其价值而言,.Net 移动版,它根本不可用)。
  • 不正确。 那是 Microsoft.VisualBasic.Compatibility 子命名空间,不是全部。 Microsoft.VisualBasic 命名空间中包含许多“核心”功能;它不会去任何地方。微软已经威胁要“淘汰”VB 6,而不是 VB.NET。他们已经多次承诺它不会去任何地方。有些人似乎仍然没有弄清楚其中的区别......
  • 这个答案最近得到了一些分数,所以引起了我的注意。我记得与@CodyGray 的对话——也许我有点小气,但我想指出,自从讨论 Microsoft.VisualBasic 命名空间如何在 .Net Core 和标准,Microsoft.VisualBasic.Interaction.InputBox() 不再存在。
【解决方案5】:

Bas 的答案理论上可以让你陷入记忆困境,因为 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;
}

【讨论】:

  • 善用内存管理。但是,添加取消按钮时会失败,因为此时 prompt 为空。允许取消提示的一个简单修复方法是将public void Dispose() 内部的prompt.Dispose(); 替换为if (prompt != null) { prompt.Dispose(); }
【解决方案6】:

其他方式: 假设您有一个 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. 如果添加了各种其他输入类型。

【讨论】:

    【解决方案7】:

    基于上述 Bas Brekelmans 的工作,我还创建了两个派生 -> “输入”对话框,允许您从用户接收文本值和布尔值(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());
        }
    }
    

    ...和文本以及多个选项之一的选择(文本框和组合框):

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

    【讨论】:

      【解决方案8】:

      Bas Brekelmans 的回答非常简洁,非常优雅。但是,我发现对于一个实际的应用程序需要更多的东西,例如:

      • 当消息文本过长时,适当增加表单。
      • 不会在屏幕中间自动弹出。
      • 不提供对用户输入的任何验证。

      这里的类处理这些限制: http://www.codeproject.com/Articles/31315/Getting-User-Input-With-Dialogs-Part-1

      我刚刚下载了源代码并将 InputBox.cs 复制到我的项目中。

      很惊讶没有更好的东西......我唯一真正的抱怨是标题文本不支持其中的换行符,因为它使用标签控件。

      【讨论】:

      • 不错的答案,但超出了所问问题的范围
      【解决方案9】:

      不幸的是,C# 仍然没有在内置库中提供此功能。目前最好的解决方案是创建一个自定义类,带有弹出一个小窗体的方法。 如果您在 Visual Studio 中工作,您可以通过单击 Project >Add class

      来完成此操作

      Visual C# 项目 >代码 >类

      将类命名为 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 方法将返回“取消”)并采取相应措施。如果用户没有输入任何内容并单击“确定”,它将告诉用户并询问他们是否要取消或重新输入文本。

      发布说明: 在我自己的实现中,我发现所有其他答案都缺少以下一项或多项:

      • 取消按钮
      • 能够在发送到方法的字符串中包含符号
      • 如何访问方法并处理返回值。

      因此,我发布了自己的解决方案。我希望有人觉得它有用。感谢 Bas 和 Gideon + 评论者的贡献,您帮助我想出了一个可行的解决方案!

      【讨论】:

        【解决方案10】:

        这是我的重构版本,它接受多行/单行作为选项

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

        【讨论】:

          【解决方案11】:

          这是 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
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2023-03-17
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多