2014-10-30 43 views
0

假設我有一個具有類似... 3控件的面板。我最終可能會添加更多控件或更改該面板中的位置。當程序啓動時,我將以編程方式隱藏控件。最終,用戶可以單擊一個按鈕,該按鈕將創建原始面板的副本以填充表單上的區域。該按鈕應該有最終的另一個點擊的選項,這意味着它們的多個實例可以用來填充這個區域。請記住,這些控件可能包含文本標籤,可以通過編程方式單獨設置或更改。我假設要做這個程序,我需要製作一個控件列表,也許是一個面板列表?我不確定如何做到這一點,考慮到我需要多次重複多次控制。重新創建一組控件

有沒有一個很好的,簡單的方法來做到這一點?我真的不想與任何第三方軟件包進行重複。

回答

2

你將不得不做的代碼,因此它會像你一樣,你可以編寫;-)

認真經常採取的做法是

  • 創建UserControl這是..和相關的表格,你想要的佈局一類..
  • 添加越來越多的實例吧..
  • ..often到FlowLayoutPanel,經常與AutoScroll

這是相當不錯,簡單的imo。

這裏是幾步之遙,但..:

  • 首先我們開始像往常一樣,通過爲UserObject類撿好聽的名字,也許「dataPanel上」或「BookItem」 ..
  • 接下來我們創建它:轉到項目瀏覽器並右鍵單擊,選擇Add-New UserControl,併爲其選擇類名稱。我將使用'BookItem'。
  • 現在您可以看到Designer向您展示一個小的空白控件。
  • 仔細觀察:您還可以看到,在項目瀏覽器中,ther現在不僅是新的'BookItem.cs'文件,而且是互補的'BookItem.Designer.cs',甚至是'BookItem.resx'文件;所以這很像創建一個新窗體..
  • 讓我們從工具箱中添加一些控件,我選擇添加一個PictureBox,4個LabelsNumericUpDown
  • 查看BookItem.Designer.cs文件:在這裏,您可以看到在Form.Desginer.cs文件中看到的所有內容:您添加到佈局的所有控件的所有設置和所有聲明。特別注意聲明(在文件底部):就像一個窗體一樣,默認情況下所有控件都聲明爲私有!
  • 我們現在可以處理佈局並編寫控件腳本。我們也可以將功能和屬性添加到UC,就像表單一樣。
  • 請注意:您需要從外部訪問的任何內容,從您的表單或其方法中讀取必須公開!所以,如果你想訪問NUpDown,讓我們把它叫做「nud_quantity」你有一個選擇
    • 您可以通過改變Modifiers性質及其在BookItem.Designer.csprivate聲明更改爲public或在設計
    • 或者你可以在UC中寫公共功能來獲取/設置其值
  • 在這兩種方式之間進行選擇是一種品味問題;如果其他開發人員將與UC類一起工作,最好通過編寫訪問方法來嚴格控制您公開的內容。

  • 編譯完項目後,您可以在工具箱中看到新的UC。

  • 您可以現在要麼從工具箱中添加它或
  • 你可以像你動態地創建任何控制代碼添加它。

讓我們來看一個例子:

想象在書店一個簡單的訂單系統:客戶已做了我們店裏的書籍搜索和呈現的書在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的實例;他們只在添加按鈕中創建。

我希望能讓你開始!

+0

你介意分享一些信息嗎?我試着製作一個UserControl,然後使用Add()函數創建一個副本,但是看起來Add()函數將控件從原始面板中移除並放入UserControl中。 – crait 2014-11-02 05:46:21

+0

事實上,你是對的。添加聽起來不像,但真的是一個'移動'。如果你創建了一個UserControl,你可以像使用其他Control一樣使用它。如果你想在代碼中添加另一個副本到你的表單中,你可以通過聲明動態創建它,就像其他任何對象一樣動態創建它,也許作爲新類型的新元素,並通過調用'new'來實例化它。.. I在短時間內會在答案中添加幾行,好嗎? (你是怎麼稱呼UC的?) – TaW 2014-11-02 06:55:10

+0

我的問題是我不想以編程的方式做到這一點。我想以一種使用我在[設計]模式下製作的面板的方式來做到這一點。這是因爲這個大型項目肯定需要通過更多的控件更新該面板。我的意思是,如果我最終必須,我會,但我會非常喜歡複製父面板並創建基於此的UserControl列表。 – crait 2014-11-02 07:16:29