65.9K
CodeProject 正在变化。 阅读更多。
Home

内容驱动的输入对话框

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.89/5 (9投票s)

2015年11月20日

CPOL

3分钟阅读

viewsIcon

17866

downloadIcon

499

为 Windows Forms 解决方案快速收集数据的自配置输入对话框。

引言

您是否曾经需要在应用程序中收集比 MessageBox 更简单的信息?开发人员可能需要花费数小时为每个数据实例编写不同的表单。此解决方案 InputDialog 将采用单个、简单的数据类型或更复杂的类,并显示一个可以为用户收集信息并返回更新的数据对象的表单。

每种数据类型的输入都仅限于有效值。

您可以使用简单和更复杂的数据类型,如下面的示例所示

    

使用代码

简单方法调用

为了只获取一个字符串(就像上面的小示例一样),代码

string s = "";
if (InputDialog.Show("What is your name?", "", ref s) == DialogResult.OK)
{
   // Do something with the 's' variable
}

通过传入一个类或结构体,可以收集更多项目。例如,要获取上面的更大示例,

public class A
{
   public enum AGender { Female, Male };
   
   public string Name { get; set; }
   public int Age { get; set; } = 25;
   public bool Married { get; set; }
   public AGender Gender { get; set; }
}

public void CollectA()
{
   A a = new A();
   InputDialog.Show("Please provide some basic information:", "Personal Info", ref a,
      SystemIcons.Information.ToBitmap());
}

组件 (Component)

如果您更喜欢可视化编码,可以将此 InputDialog.cs 文件添加到您的项目中,然后您应该在您的工具箱中看到一个 InputDialog 项。

将此组件添加到您的表单中将会在组件托盘中放置一个项目

然后您可以在“属性”面板中查看并进行更改

从您的表单调用它将非常简单,就像

int data = 100;
inputDialog1.Data = data;
if (inputDialog1.ShowDialog(this) == DialogResult.OK)
   data = (int)inputDialog1.Data;

您将获得

使用属性控制显示

如果使用类或结构体,您甚至可以使用 InputDialogItem 属性控制标签和显示顺序

public class A
{
   public enum AGender { Female, Male };
   
   [InputDialogItem(Hidden = true)]
   public bool unshownSetting = true;

   [InputDialogItem("Full name", Order = 0)]
   public string Name { get; set; }
   [InputDialogItem(Order = 1)]
   public int Age { get; set; } = 25;
   public bool Married { get; set; }
   [InputDialogItem(Order = 2)]
   public AGender Gender { get; set; }
}

所有公共字段和属性都将显示,直到它们的 InputDialogItem.Hidden 属性设置为“true”。

顺序有些随意,因为使用反射来收集这些值。要指定顺序,请设置 InputDialogItem.Order 属性。任何有序项目都将优先于无序项目。

默认情况下,每个项目的标签是字段或属性的名称。要更改它,请使用 InputDialogItem 属性的第一个参数,并将其设置为您想要的值(如上面的 Name 属性)。

上面的类将产生此对话框

支持多种类型

所有以下类型都支持作为类或结构体的成员或作为独立对象

Boolean, Byte, SByte, Int16, UInt16, Int32, UInt32, Int64, UInt64, IntPtr, UIntPtr, Char, Double, Single, Enum, Decimal, DateTime, String, TimeSpan 和 Guid

如果用户尝试添加无效字符串,则每个都会显示错误,并且每个都会阻止键入不支持的字符。

学到的教训

使用反射

为了完成这个输入对话框,我当然使用反射。我确定传入对象的类型,然后使用 Type 类的各种方法和属性来决定如何构建 UI。

由于许多类型实际上是结构体或基本类型,因此我需要将值作为引用传入,以便在成功返回时可以更改其值。

TableLayoutPanel 的可怕科学

我希望我可以说我大部分时间都在编码。不。我大部分时间都花在调试 TableLayoutPanel 的奇怪机制上。我学到了什么?

  1. 单元格内控件的 Margin 非常重要。如果 Margin 全为零,则对控件的处理方式与没有控件时的处理方式不同。如果 Margin 有一个值,则整行或整列都会受到影响。
  2. 设置 MinimumSize 和 MaximumSize 通常是确保单元格大小的唯一方法。
  3. 让标签换行很困难。在内部,它对大小调整有正确的答案,但无法应用它们。
    1. 设置 AutoSize = true 和 Dock = DockStyle.Top
    2. 将标签添加到表格后,如果其宽度 < PreferredWidth,则设置其 MinimumSize = Size

很酷的事件处理快捷方式

是否需要处理事件但又懒得构建处理程序?试试这个

TextBox tb = new TextBox();
tb.Enter += (s, e) => tb.SelectAll()

这将导致在输入控件时选择 TextBox 中的文本。

历史

2015年11月11日 - 初始发布

© . All rights reserved.