你将不得不做的代码,因此它会像你一样,你可以编写;-)
认真经常采取的做法是
- 创建
UserControl
这是..和相关的表格,你想要的布局一类..
- 添加越来越多的实例吧..
- ..often到
FlowLayoutPanel
,经常与AutoScroll
这是相当不错,简单的imo。
这里是几步之遥,但..:
让我们来看一个例子:
想象在书店一个简单的订单系统:客户已做了我们店里的书籍搜索和呈现的书在DataGridView
“dgv_bookList列表',只读,多选。在右边有一个代表购物车的'flp_cart'FlowLayoutPanel
。并且我们有一个命令按钮'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);
}
}
这将增加一个BookItem在DGV每个所选行。
有几件事情要注意,上面的代码:
我传递的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)
功能。
另请注意我的标签是多么愚蠢的命名!你可以做得比这更好,我希望!
另请注意我如何访问'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;
经常preferrable:接入功能,也许是这样的:
public int quantity() { return (int) numericUpDown1.Value; }
或者,当然还有一个属性:
public int quantity { get { return (int)numericUpDown1.Value; } }
另请注意,我将BookData项目的名称设置为第一个数据项的一些变体,即我的书籍ID。这可能会更好,或者更好,发生在构造函数中;并且应该进行检查以防止两次添加相同的项目。
所有的一切可以说,在使用用户控件是非常喜欢使用表单,包括所有常见的方法或技巧形式间通信:保持引用,揭露成员,创建属性和功能..
最后一个注意:与表单或子类控件一样,有一个问题:通过将它们放置在设计器中,您可以在设计时指定设计师对您的UC的显示器的责任。
这通常很好;但也可能引入微妙的错误,使设计师无法显示控件。在设计人员能够显示控件或包含它的任何表单之前,您需要纠正这些问题。让我们来看看这样的问题的一个简单的例子:
让我们的脚本中的图片框在UC“pb_cover”的Paint事件:
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为空。这里的补救很简单:给Brush声明添加一个默认值,一切都很好。其他情况可能需要更多的思考..
我甚至没有遇到问题顺便说一句,因为我没有放置在Form上的BookItem的实例;他们只在添加按钮中创建。
我希望能让你开始!
你介意分享一些信息吗?我试着制作一个UserControl,然后使用Add()函数创建一个副本,但是看起来Add()函数将控件从原始面板中移除并放入UserControl中。 – crait 2014-11-02 05:46:21
事实上,你是对的。添加听起来不像,但真的是一个'移动'。如果你创建了一个UserControl,你可以像使用其他Control一样使用它。如果你想在代码中添加另一个副本到你的表单中,你可以通过声明动态创建它,就像其他任何对象一样动态创建它,也许作为新类型的新元素,并通过调用'new'来实例化它。.. I在短时间内会在答案中添加几行,好吗? (你是怎么称呼UC的?) – TaW 2014-11-02 06:55:10
我的问题是我不想以编程的方式做到这一点。我想以一种使用我在[设计]模式下制作的面板的方式来做到这一点。这是因为这个大型项目肯定需要通过更多的控件更新该面板。我的意思是,如果我最终必须,我会,但我会非常喜欢复制父面板并创建基于此的UserControl列表。 – crait 2014-11-02 07:16:29