效果:
描述:
這是一個可折疊的菜單導航,主要是由panel、picturebox、label完成,界面的顏色用來區分一下各個組合控件,便於調試。
首先,首先是ImageButton:

這個是由PictureBox和Label構成。
1.文字部分的居中需要設置label的寬度為父容器的寬度。
2.圖片設置 picBox.SizeMode = PictureBoxSizeMode.StretchImage
然后是單個的菜單 命名為:ButtonGroup:

頂部灰色的是一個label,綠色里面的是一個包含ImageButton的列表。
1.頂部這個label注冊了一個click事件,是為了完成點擊它的時候會展開。
最后是整個的菜單,就是由ButtonGroup組成的一個list,我給它命名為:CustomNavBar。
這里需要注意的是:
事件的封裝,像這種自定義控件,都是要定義自定義事件,並且把它暴露出來,元控件觸發的時候,才觸發這個暴露出來的控件。代碼類似這種:
private void PicBoxClick(object sender,EventArgs args)
{
PictureBoxClick?.Invoke(sender, this.text);
}
PicBoxClick是PictureBox控件的原生Click事件,PictureBoxClick是我們自己定義的事件,這個事件需要到控件外部注冊,就像這樣:
for (int i = 0; i < _listImageButton.Count; i++)
{
var imgButton = _listImageButton[i];
imgButton.Top = i * imgButton.Height;
imgButton.Left = 0;
imgButton.PictureBoxClick += ImgButton_PictureBoxClick;
ButtonArea.Controls.Add(imgButton);
}
這段代碼中,_listImageButton是屬於ButtonGroup控件里的集合,這樣做,最終點擊PictureBox的時候,其實是調用ImgButton_PictureBoxClick這個方法里的內容。
假如這個ButtonGroup已經是最外層的自定義控件了,那么這個ImgButton_PictureBoxClick就屬於供這個完整的自定義控件使用人也就是客戶自己自定義的事件了,這個里面的代碼就可以根據不同的客戶,內容就可以不同了。
因為這個控件最外層的自定義控件是CustomNavBar,所以在CustomNavbar里還自定義了一個相同委托的事件:
public delegate void ImageButtonClick(object o,string moduleName);
public event ImageButtonClick NavButtonClick;
這代碼也是我從其他地方下載的,然后自己看了一篇,在自己敲的。敲的過程中,了解到了內部類的使用,最大的收獲是:一般窗體都是要有partial修飾的,而InitializeComponent()方法都是放在自動生成的代碼里的,做這個控件的時候,我還是自己第一次這樣通過寫代碼的方式來初始化一個控件。
代碼:

public partial class CustomNavBar : UserControl { public CustomNavBar() { InitializeComponent(); InitializeButtonGroup(); pnlMain.BackColor = Color.DarkOliveGreen; ResetMenu(); } private string _jsonString; /// <summary> ///暴露接口,可從外部(數據庫)獲得菜單的信息 /// </summary> public string JsonString { get { return _jsonString; } set { _jsonString = value; } } private List<ButtonGroup> listGroup; private int currentItemIndex; public delegate void ImageButtonClick(object o,string moduleName); public event ImageButtonClick NavButtonClick; public void InitializeButtonGroup() { listGroup = new List<ButtonGroup>() { new ButtonGroup("歡迎使用", new List<ImageButton>() { new ImageButton("歡迎使用",Resources.LogoMain), new ImageButton("員工信息管理",Resources.LogoManageEmployee) }), new ButtonGroup("系統設置", new List<ImageButton>(){ new ImageButton("部門管理", Resources.LogoManageDepartment)}), new ButtonGroup("退出系統",null) }; ButtonGroup bgPre=null; int sum = 0; for (int i = 0; i < listGroup.Count; i++) { int height = bgPre == null ? 0 : bgPre.Height; sum += height; var buttonGroup = listGroup[i]; buttonGroup.Tag = i; buttonGroup.SetButtonLocation(); buttonGroup.ImageButtonClick += new ImageButtonClick(NavClick); buttonGroup.Left = 0; buttonGroup.Top = sum; buttonGroup.ItemMeunClick += ButtonGroup_ItemMeunClick; this.pnlMain.Controls.Add(buttonGroup); bgPre = buttonGroup; } } private void NavClick(object sender,string moduleName) { NavButtonClick?.Invoke(sender, moduleName); } private void ButtonGroup_ItemMeunClick(object sender, EventArgs e) { Label lblItem = sender as Label; currentItemIndex = 0; if (lblItem != null) { ButtonGroup bg = lblItem.Parent as ButtonGroup; if (bg != null) { currentItemIndex = Convert.ToInt32(bg.Tag); } } ResetMenu(); } private void ResetMenu() { if (listGroup != null && listGroup.Count > 0) { int barHeight = 22; int totalHeight = pnlMain.Height; for (int n = 0; n < listGroup.Count; n++) { ButtonGroup buttonGroup = listGroup[n]; int thisIndex = Convert.ToInt32(buttonGroup.Tag); if (thisIndex <= currentItemIndex) { buttonGroup.Top =n * barHeight; } else { buttonGroup.Top = totalHeight - (listGroup.Count-n) * barHeight; } if (thisIndex == currentItemIndex) { buttonGroup.Height = totalHeight - (listGroup.Count - 1) * barHeight; } else { buttonGroup.Height = barHeight; } } } } #region ButtonGroup public class ButtonGroup : UserControl { private Label lblItem = new Label(); private string text; private Panel ButtonArea = new Panel(); public event EventHandler ItemMeunClick; public event ImageButtonClick ImageButtonClick; public ButtonGroup(string txt,List<ImageButton> listImageButton) { this.text = txt; this._listImageButton = listImageButton; this.Initialize(); } private List<ImageButton> _listImageButton; public List<ImageButton> ListImageButton { get { return _listImageButton; } set { _listImageButton = value; } } public void Initialize() { lblItem.Text = this.text; lblItem.Height = 22; lblItem.Width = 156; lblItem.TextAlign = ContentAlignment.MiddleCenter; lblItem.BackColor = Color.DarkGray; lblItem.ForeColor = Color.DarkRed; lblItem.Cursor = Cursors.Hand; lblItem.Click += LblItem_Click; this.Width = 156; this.BackColor = Color.DarkOliveGreen; this.Controls.Add(lblItem); this.Controls.Add(ButtonArea); } private void LblItem_Click(object sender, EventArgs e) { ItemMeunClick?.Invoke(sender, e); } public void SetButtonLocation() { ButtonArea.Location = new Point(0, 22); int buttonCount = _listImageButton == null ? 0 : _listImageButton.Count; int Height = 62; //ButtonArea.BackColor = Color.Red; ButtonArea.Size = new Size(156, buttonCount * Height); if (_listImageButton != null && _listImageButton.Count > 0) { for (int i = 0; i < _listImageButton.Count; i++) { var imgButton = _listImageButton[i]; imgButton.Top = i * imgButton.Height; imgButton.Left = 0; imgButton.PictureBoxClick += ImgButton_PictureBoxClick; ButtonArea.Controls.Add(imgButton); } } this.Height = lblItem.Height + ButtonArea.Height; } private void ImgButton_PictureBoxClick(object o, string moduleName) { ImageButtonClick?.Invoke(o, moduleName); } } #endregion #region ImageButton public class ImageButton : UserControl { private string text; private Image img; private PictureBox picBox=new PictureBox(); private Label lblText = new Label(); public event ImageButtonClick PictureBoxClick; public ImageButton(string txt, Image image) { this.text = txt; this.img = image; this.InitialImageButtonControl(); } public void InitialImageButtonControl() { picBox.Size = new Size(40, 40); picBox.Left = 57; picBox.Top = 0; picBox.Image = this.img; picBox.Anchor = AnchorStyles.Top; picBox.SizeMode = PictureBoxSizeMode.StretchImage; picBox.Cursor = Cursors.Hand; picBox.Click += new EventHandler(PicBoxClick); lblText.Width = 156; lblText.Height = 22; lblText.Location = new Point(0, 40); lblText.Text = this.text; lblText.TextAlign = ContentAlignment.MiddleCenter; lblText.BackColor = Color.DarkOliveGreen; lblText.ForeColor = Color.DarkGray; lblText.Cursor = Cursors.Hand; this.Height = picBox.Height + lblText.Height; this.Controls.Add(picBox); this.Controls.Add(lblText); } private void PicBoxClick(object sender,EventArgs args) { PictureBoxClick?.Invoke(sender, this.text); } } #endregion }