問題: 在系統開發中,布局界面設計是比較重要的一個環節,我曾在一家甲方公司做過MES開發,見過的系統界面五花八門,有100號人,就有近100種樣式,開發的小系統數不清,命名規范更是雜亂無章。所以作為IT項目的管理者,管理這系統和人員這是一件很頭痛的事情,但這跟他們的系統管理有很大關系。
最后在進行系統升級中,原有的系統基本上都廢棄了,我寧願重新了解需求,重新投入時間開發而不想去看一個方法有近千行代碼,嵌套不少於50個if…else...邏輯,改程序的人,會一邊改一邊罵設計此程序的人~~~,感覺與主題扯遠了,還是以系統界面部局為主題。
我的一些改善措施:
不以花哨的界面為主,先以傳統的方式進行說明設計原理:
制造業系統一般要求系統操作簡單,易用,靈活,所以要做到這幾點,起碼要有橫向菜單,左導航菜單功能,狀態欄,系統內容顯示區,其他的個人認為較少用到。
用到的控件主要為:
MenuStrip,ToolStrip,StatusStrip,ToolStripContainer,同時結合一個開源布局控件”WeifenLuo.WinFormsUI.Docking”,這幾個控件相互配合,一樣可以設計出相對合理的系統框架。
現在我以一個《地理導航系統》為例,做一些簡單原理介紹。
設計的步驟:
1. 建一個項目”GMapGuide”,新建三個Form,分別為GMapForm,GuideBarForm,MainForm,添加入谷歌地圖html文件”GoogleMap1.html”,如下圖:
2.接着引入”WeifenLuo.WinFormsUI.Docking.dll”,並在工具箱中添加DockPanel控件,此控件來源網上很多地方可以下載到,如下圖:
3.在主窗體MainForm中,添加”ToolStripContainer”,並設為布滿整個主窗口Dock屬性設為Fill即可,分別在ToolStripContainer頂部拖入一個MenuStrip和一個ToolStrip控件,底部拖入一個StatusStrip,根據需要設置屬性,如下圖:
4.在ToolStripContainer控件的內容區域-toolStripContainer1.ContentPanel中添加DockPanel控件,並設置為布滿整個區域,如下圖:
在這里,DockPanel需要做一些設置,因為我主窗體不是Mdi,即IsMdiContainer=False,需要設DocumentStyle=DockingWindow,如果主窗體是Mdi,此處需要設為DockingMdi,此處設置參考下邊圖示:
5.把其他的窗體都繼承DockContent,如下代碼:
namespace GMapGuide { public partial class GMapForm : DockContent { //具體代碼邏輯} } }
namespace GMapGuide { public partial class GuideBarForm: DockContent { //具體代碼邏輯 } }
6.分別對繼承DockContent的窗體作一些設置:
- HideOnClose:True,意思是當窗體隱藏時,只是隱藏窗體的功能,沒有真正關閉窗體。
- DockAreas: "Float, DockLeft, DockRight, DockTop, DockBottom".
- CloseButton:True
這幾個屬性從名字上看應該知道什么意思,不作具體解釋。
針對左導航條(左導航菜單),需要把ShowHint設為DockLeft,就我做的系統,其他屬性的不需要做設置,這里點到為止。
7.最后一步啦,在主窗體MainForm中編寫代碼,如下:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Text; using System.Windows.Forms; using WeifenLuo.WinFormsUI.Docking; namespace GMapGuide { public partial class MainForm : Form { private GuideBarForm gMapForm; private GMapForm toolBarForm; public MainForm() { InitializeComponent(); gMapForm = new GuideBarForm(); toolBarForm = new GMapForm(gMapForm); } private void MainForm_Load(object sender, EventArgs e) { gMapForm.Show(dockPanel1); toolBarForm.Show(dockPanel1); } } }
秀一下成果,大家別給我丟雞蛋:
bug來了: 當窗口是自動隱藏的時候,好像出來的大小一般比實際的大,確實是影響美觀,還閃着抖動一下,怪怪的感覺。
解決問題的措施:
園中參考了華兄的解決辦法,不錯滴,很贊他的技術,不過一些細節他沒有寫清楚,初學的人要摸個半天才搞明白(我這小菜就如此
).
先看控件內部機制:
[LocalizedCategory("Category_Docking")] [LocalizedDescription("DockContent_AutoHidePortion_Description")
[DefaultValue(0.25)] public double AutoHidePortion { get { return DockHandler.AutoHidePortion; } set { DockHandler.AutoHidePortion = value; } }
- 我先把窗體GuideBarForm 的AutoHidePortion設為0.17,如圖:
默認的大小是0.25,這個參數是可以修改的。因為控件提供了一個保存布局狀態的方法,它默認是沒有保存的,如果需要記住調整的窗口大小,我加上幾段代碼就可以解決了。
在關閉系統時,保存一下狀態設置,如下代碼:
private void MainForm_FormClosing(object sender, FormClosingEventArgs e) { dockPanel1.SaveAsXml(Path.Combine(Application.StartupPath, "CustomUI.xml")); }
加載部局代碼:
#region 加載布局 private IDockContent GetContentFromPersistString(string persistString) { try { if (persistString == typeof(GuideBarForm).ToString()) { if (gMapForm == null) { return new GuideBarForm(); } else { return gMapForm; } } if (persistString == typeof(GMapForm).ToString()) { if (toolBarForm == null) { return new GMapForm(gMapForm); } else { return toolBarForm; } } } catch (Exception ex) { Console.WriteLine(persistString); } throw new Exception(); } #endregion
加載窗體時,加入如下代碼:
private void MainForm_Load(object sender, EventArgs e) { //加載 string uiFile = Path.Combine(Application.StartupPath, "CustomUI.xml"); if (File.Exists(uiFile)) { DeserializeDockContent ddContent = new DeserializeDockContent(GetContentFromPersistString); dockPanel1.LoadFromXml(uiFile, ddContent); } gMapForm.Show(dockPanel1);//放在加載設置后面
toolBarForm.Show(dockPanel1); }//放在加載設置后面
注意:很多人搞不成功,跟這個位置有關系,顯示窗體一定要在加載功能后面,否則報錯:”The DockPanel has already been initialized.”
到這里,已基本解決這個框架布局問題。
把幾個效果圖展示一下,看效果:
(1)圖一:
(2)圖二:
(3)圖三:
總結:
這篇博文主要是說明一些基本的系統框架布局,主要是針對菜單欄,左導航菜單,以及WeifenLuo.WinFormsUI.Docking的使用說得比較多。
WeifenLuo.WinFormsUI.Docking的確是很強大的布局工具,但是還是有些缺陷:
(1)隱藏后顯示問題,如上有解決的辦法。
(2)個人覺得具有換膚的系統,用它就會顏色上明顯不協調,所以它目前只限於傳統Winform的框架設計,要想用它還得大動手術。(這個我后續在說換膚功能時,會解釋改善措施,我不知道我這樣會不會侵權啊?要是有人支持我,我搞給大家看!)。
在系統框架布局上,我上面講的僅僅是很基礎的做法,還有很多細節需要注意的地方,本人知識有限,還得高人指點,好補充知識面。