Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/266.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 重新创建一组控件_C#_Windows_Duplicates - Fatal编程技术网

C# 重新创建一组控件

C# 重新创建一组控件,c#,windows,duplicates,C#,Windows,Duplicates,假设我有一个面板,上面有。。。其中包含3个控件。我可能会添加更多控件或更改面板中的位置。当程序启动时,我将以编程方式隐藏控件。最终,用户可以单击一个按钮,该按钮将创建原始面板的副本,以填充表单上的一个区域。该按钮应具有再次单击的选项,这意味着这些按钮的多个实例可能会填充此区域。请记住,这些控件中可能有文本标签,可以在以后以编程方式单独设置或更改。我假设要做这个程序,我需要做一个控件列表,也许是一个面板列表?考虑到我需要多次复制多个控件的事实,我不太确定如何做到这一点 有没有一个好的,简单的方法来

假设我有一个面板,上面有。。。其中包含3个控件。我可能会添加更多控件或更改面板中的位置。当程序启动时,我将以编程方式隐藏控件。最终,用户可以单击一个按钮,该按钮将创建原始面板的副本,以填充表单上的一个区域。该按钮应具有再次单击的选项,这意味着这些按钮的多个实例可能会填充此区域。请记住,这些控件中可能有文本标签,可以在以后以编程方式单独设置或更改。我假设要做这个程序,我需要做一个控件列表,也许是一个面板列表?考虑到我需要多次复制多个控件的事实,我不太确定如何做到这一点


有没有一个好的,简单的方法来做到这一点?我真的不想用任何类型的第三方软件包进行复制。

您必须用代码进行复制,因此它将尽可能好地编码;-)

说真的,最常采取的做法是

  • 创建一个
    UserControl
    ,它是一个与表单相关的类,具有您想要的布局
  • …并添加越来越多的实例
  • ..通常用于
    流程布局面板
    ,通常用于
    自动滚动
在我看来,这是非常好和简单的

不过,这里有一小段路要走

  • 首先,像往常一样,我们首先为UserObject类选择一个好的名称,可能是“DataPanel”或“BookItem”
  • 接下来我们创建它:转到项目资源管理器并右键单击,选择
    addnewusercontrol
    ,并为它指定您选择的类名。我将使用“BookItem”
  • 现在您可以看到设计器向您显示一个小的空控件
  • 仔细看:您还可以看到,在项目浏览器中,现在不仅有新的“BookItem.cs”文件,还有补充的“BookItem.Designer.cs”,甚至还有一个“BookItem.resx”文件;因此,这与创建新表单非常相似
  • 让我们从工具箱中添加一些控件,我选择添加一个
    PictureBox
    、四个
    标签和一个
    NumericUpDown
  • 查看
    BookItem.Designer.cs
    文件:在这里,您可以看到在
    Form.Desginer.cs
    文件中看到的东西:添加到布局中的所有控件的所有设置和所有声明。特别注意声明(在文件的底部):就像表单一样,默认情况下所有控件都声明为私有
  • 我们现在可以处理布局并编写控件脚本。我们还可以向UC添加函数和属性,就像表单一样
  • 请注意:您需要从外部访问、从表单或其方法读取的任何内容都必须是公共的!因此,如果您想访问NUpDown,让我们称之为“nud_quantity”,您可以选择
    • 您可以将其在
      BookItem.Designer.cs
      中的声明从
      private
      更改为
      public
      ,或者通过更改
      修饰符
      属性在设计器中更改
    • 或者您可以在UC中编写一个公共函数来获取/设置其值
  • 在这两种方式之间进行选择是一个品味问题;如果其他开发人员将使用UC类,那么最好通过编写访问方法来密切控制您公开的内容

  • 编译项目后,您可以在工具箱中看到新的UC

  • 现在,您可以从工具箱中添加它,也可以从
  • 您可以像动态创建的任何控件一样将其添加到代码中
让我们看一个例子:

想象一下书店中的一个简单订购系统:客户在我们商店中搜索了书籍,并在
DataGridView
“dgv_bookList”中显示了一个书籍列表,该列表为只读、多选。右侧有一个
FlowLayoutPanel
代表购物车的“flp_cart”。我们有一个命令按钮“cb_addItems”,用于将所选书籍添加到购物车中

按钮
的脚本可能如下所示:

private void cb_addItems_Click(object sender, EventArgs e)
{
    if (dgv_bookList.SelectedRows.Count <= 0) return;

    foreach (DataGridViewRow row in dgv_bookList.SelectedRows)
    {
        BookItem book = new BookItem (row);
        book.label1.Text = "#00" + book.label1.Text;
        book.Name = book.label1.Text;
        flp_cart.Controls.Add(book);

    }
}
public bookItem()
{
    InitializeComponent();
}

public bookItem(DataGridViewRow bookData)
{
    InitializeComponent();
    label1.Text = bookData.Cells[0].FormattedValue.ToString();
    label2.Text = bookData.Cells[1].FormattedValue.ToString();
    label3.Text = bookData.Cells[2].FormattedValue.ToString();
    label4.Text = bookData.Cells[3].FormattedValue.ToString();
}
public int quantity() { return (int) numericUpDown1.Value; } 
相反,您可以编写一个
公共setData(DataGridViewRow bookData)
函数

还要注意我的标签命名有多么愚蠢!我希望你能做得更好

还要注意我是如何访问“label1”并从表单中的按钮修改其文本的;为此,我必须更改Desginer.cs文件中的声明:

private System.Windows.Forms.PictureBox pb_cover;
public System.Windows.Forms.Label label1;          // <<----expose this label !
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.NumericUpDown numericUpDown1;
或者,当然是财产:

public int quantity {  get { return (int)numericUpDown1.Value;  }  }
还请注意,我将BookData项的名称设置为第一个数据项my book id的某个变体。这也可能发生在构造函数中,或者更好;应该有一个检查,以防止添加相同的项目两次

总之,可以说,使用UserControls与处理表单非常相似,包括表单间通信的所有常用方法或技巧:保留引用、公开成员、创建属性和函数

最后一个注意事项:与表单或子类控件一样,有一个问题:将它们放置在设计器中,您可以指定设计器负责在设计期间显示您的UC

这通常很好;但是,也可能会引入一些微妙的错误,使设计者无法显示控件。在设计器能够显示控件或包含它的任何窗体之前,需要更正这些问题。让我们看一个此类问题的简单示例:

让我们在UC中为PictureBox“pb_封面”的绘画事件编写脚本:

public Brush myBrush = null;

private void pb_cover_Paint(object sender, PaintEventArgs e)
{
    if (pb_cover.Image == null)
    {
        Size  s = pb_cover.ClientSize;
        e.Graphics.FillRectangle(myBrush, 0, 0, s.Width, s.Height);
        e.Graphics.DrawLine(Pens.Red, 0, 0, s.Width, s.Height);
        e.Graphics.DrawLine(Pens.Red, s.Height, 0, 0, s.Width);
    }
}
让我们修改添加按钮中的代码:

 BookItem book = new BookItem (row);
 book.label1.Text = "#00" + book.label1.Text;
 book.myBrush = Brushes.OliveDrab;
 flp_cart.Controls.Add(book);
现在,如果你运行程序,一切都会好起来。即使您尝试在设计师中查看UC,也可能存在或不存在问题。但是,一旦您尝试打开放置UC的表单,设计工程师将崩溃并告诉您它无法工作,因为笔刷为空。这里的补救方法很简单:在笔刷声明中添加一个默认值,一切正常。其他