重新创建一组控件

时间:2014-10-30 10:00:48

标签: c# windows duplicates

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

有一个很好的,简单的方法吗?我真的不想与任何类型的第三方包装进行复制。

1 个答案:

答案 0 :(得分:2)

你必须在代码中完成它,因此它会像你可以编码一样好;-)

严重的是,最常用的课程是

  • 创建一个UserControl,它是一个与表单相关的类,具有您想要的布局。
  • ..并添加越来越多的实例..
  • ..通常是FlowLayoutPanel,通常是AutoScroll

这是非常好的和简单的imo。

这是一个很短的步行路程..:

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

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

  • 您现在可以从工具箱或
  • 添加它
  • 您可以将其添加到代码中,就像您动态创建的任何控件一样。

让我们看一个例子:

想象一下书店里的一个简单的订单系统:客户已经对我们商店的书籍进行了搜索,并在DataGridView< dgv_bookList'中显示了一系列书籍,只读,多选。在右边有一个FlowLayoutPanel' flp_cart'代表购物车。我们有一个命令按钮' cb_addItems'将所选书籍添加到购物车。

Button可能是这样的脚本:

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

    }
}

这将为DGV中的每个选定行添加一个BookItem。

以上代码需要注意几点:

我将一个DataGridViewRow传递给UC的构造函数,以便它可以直接设置其标签!这意味着,除了desginer为我们构建的无参数构造函数之外,我们还需要编写第二个构造函数,可能是这样的:

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 setData(DataGridViewRow bookData)函数。

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

另请注意我如何访问&#39; label1&#39;并从表单中的按钮修改其文本;要做到这一点,我必须在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() { return (int) numericUpDown1.Value; } 

或者,当然是财产:

public int quantity {  get { return (int)numericUpDown1.Value;  }  }

另请注意,我将BookData项的名称设置为第一个数据项的某个变体,即我的书ID。在构造函数中也可能发生这种情况,或者更好;并且应该检查以防止两次添加相同的项目..

总而言之,使用UserControls非常类似于使用Forms,包括用于表单间通信的所有常用方法或技巧:保留引用,公开成员,创建属性和函数..

最后一点注意:与表单或子类控件一样,有一个问题:通过将它们放置在设计器中,您可以在设计时为设计人员分配责任,以显示您的UC。

这通常很好;然而,也有可能引入微妙的错误,使设计师无法显示控件。在设计人员能够显示控件或包含控件的任何表单之前,您需要更正这些问题。让我们来看一个这样一个问题的简单例子:

让我们编写PictureBox的Paint事件&#39; pb_cover&#39;在加州大学:

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的表单,Desginer就会崩溃并告诉你它无法工作,因为Brush是null。这里的补救措施很简单:在Brush声明中添加一个默认值,一切都很好。其他情况可能需要更多思考..

我甚至没有遇到问题btw,因为我没有在Form上放置BookItem的实例;它们只在添加按钮中创建..

我希望能让你开始!