Management Studio是我在WinForms小項目開發過程中搭建起來的一個插件式結構的應用程序框架,因為簡單靈活又容易擴展,現在將它開源供讀者參考。
跑起來的效果圖如下所示,具備選項卡式多文檔界面,Office 2007藍色風格,插件式結構等特性。
選項卡式多文檔界面 Tab MDI
通過Infragistics Dock控件,可以很容易的實現選項卡式多文檔界面。只需要在主界面的窗體設計器組件欄中拖入一個ultraTabbedMdiManager控件,設定主窗體的IsMdiContainer屬性為true,剩下的工作就交由這個組件來負責。
當我們用下面的代碼創建一個子窗體時,它會自動的產生一個選項卡文檔,參考下面代碼。
Startup frm = new Startup();
frm.MdiParent = this;
frm.Show();
從上面的代碼片段中可以看到仍舊是MDI的編程風格,但產生的結果是選項卡式的界面。
插件結構 PlugIn
借助於反射機制,讀取當前程序集中的類型定義,找到包含有指定特性的類型,創建它的實例,即可實現基本的插件式結構。
首先,我們給需要的窗體類增加FunctionCode特性,參考下面的代碼。
[FunctionCode("DataSetReader")]
public partial class DataSetReader : FormBase
{
public DataSetReader()
{
InitializeComponent();
}
然后修改創建窗體的代碼,從當前的程序集類型中搜索,找到指定特性的窗體的類型后,創建它的實例。關鍵的代碼如下面所示。
Assembly assembly = Assembly.GetExecutingAssembly();
foreach (Type type in assembly.GetTypes())
{
try
{
object[] attributes = type.GetCustomAttributes(typeof(FunctionCode), true);
foreach (object obj in attributes)
{
FunctionCode attribute = (FunctionCode)obj;
if (!string.IsNullOrEmpty(attribute.Value))
{
if (!_formBaseType.ContainsKey(attribute.Value))
_formBaseType.Add(attribute.Value, type);
if (formBaseType == null && attribute.Value.Equals(functionCode,StringComparison.InvariantCultureIgnoreCase))
formBaseType = type;
}
最后,我們添加一個菜單項,用於顯示當前已經存在的功能編碼給用戶選擇,菜單項的實現用XML文件定義,參考項目中嵌入的資源文件ListItem.xml。
<?xml version="1.0" encoding="utf-8" ?>
<Items>
<Item Index="0" Text="DataSet Reader" Tag="DataSetReader" ImageIndex="17"></Item>
<Item Index="1" Text="Translation" Tag="Translation" ImageIndex="32"></Item>
<Item Index="2" Text="String Builder" Tag="TextToStringBuilder" ImageIndex="33"></Item>
<Item Index="3" Text="License Generator" Tag="GenLicense" ImageIndex="7"></Item>
<Item Index="4" Text="Query Generator" Tag="QueryGenerator" ImageIndex="34"></Item>
<Item Index="5" Text="Lookup Generator" Tag="LookupGenerator" ImageIndex="35"></Item>
<Item Index="6" Text="Report Generator" Tag="ReportGenerator" ImageIndex="36"></Item>
<Item Index="7" Text="Query Lookup" Tag="QueueLookUpForm" ImageIndex="37"></Item>
<Item Index="8" Text="Database Update" Tag="DatabaseUpdate" ImageIndex="38"></Item>
</Items>
運行時讀取嵌入的資源項,生成如下界面所示的列表視圖。
雙擊列表視圖中的項或選擇項后點OK都可以打開指定的功能對應的窗體。
Office 2007 藍色風格 Office Render
借用CodeProject上的一篇文章提供的組件,我們只需要在主界面的OnLoad方法中增加2行代碼即可實現藍色的界面風格。
private void Form1_Load(object sender, EventArgs e)
{
ToolStripManager.Renderer = new ERP.Misc.Office2007Renderer();
statusStrip.Renderer = new ERP.Misc.Office2007Renderer();
Office Render組件已經設置好了默認的顏色風格,並不需要我們去調整。程序員大多沒有色彩知識,ASP.NET 組件Ext.NET也是一個藍色風格的組件,它內置的藍色風格很受歡迎,程序員不喜歡也沒有能力去維護這個復雜的配色方案,只想拿來用就可以了。
private static Color _c1 = Color.FromArgb(167, 167, 167);
private static Color _c2 = Color.FromArgb(21, 66, 139);
private static Color _c3 = Color.FromArgb(76, 83, 92);
private static Color _c4 = Color.FromArgb(250, 250, 250);
private static Color _c5 = Color.FromArgb(248, 248, 248);
private static Color _c6 = Color.FromArgb(243, 243, 243);
private static Color _r1 = Color.FromArgb(255, 255, 251);
private static Color _r2 = Color.FromArgb(255, 249, 227);
private static Color _r3 = Color.FromArgb(255, 242, 201);
private static Color _r4 = Color.FromArgb(255, 248, 181);
后台線程 WorkerThreadBase
WorkerThreadBase也是CodeProject上面的一篇文章的代碼。通常與界面相關的長時間的操作我們應該用BackgroundWorker組件封裝起來以避免界面死鎖。如果不是與界面相關的操作,我們可以用多線程,並行等方法實現,也可以用這里提到的WorkerThreadBase,它的例子代碼如下所示,下面是一個復制文件的例子。
public class CopyFileWorker : WorkerThreadBase
{
private static CopyInfo _copyInfo;
public CopyFileWorker(CopyInfo copyInfo)
{
_copyInfo = copyInfo;
}
protected override void Work()
{
copyFiles(_copyInfo);
}
private void copyFiles(CopyInfo copyInfo)
{
//check if the user called Stop
if (StopRequested)
{
Console.WriteLine("User called Stop.");
Console.WriteLine("Terminating thread while copying directory '{0}'.", copyInfo.Source);
return;
}
if (!Directory.Exists(copyInfo.Destination))
{
Directory.CreateDirectory(copyInfo.Destination);
}
Console.WriteLine("CopyFiles from '{0}' to '{1}' {2}...", copyInfo.Source,copyInfo.Destination, copyInfo.Recursive ? "recursive" : "non-recursive");
foreach (string file in Directory.GetFiles(copyInfo.Source))
{
string destination = Path.Combine(copyInfo.Destination,Path.GetFileName(file));
File.Copy(file, destination);
}
if (copyInfo.Recursive)
{
foreach (string directory in Directory.GetDirectories(copyInfo.Source))
{
string destination = Path.Combine(copyInfo.Destination,Path.GetFileName(directory)); //get the directory name for the path
copyFiles(new CopyInfo(directory,destination,copyInfo.Recursive));
}
}
Console.WriteLine("CopyFiles finished.");
}
繼承於WorkerThreadBase,將要操作的方法放到Work方法中重寫,啟動一個或多個后台線程任務的例子代碼參考下面的程序片段。
DummyWorker dummyWorker = new DummyWorker();
dummyWorker.Start();
CopyFileWorker copyFileWorker = new CopyFileWorker(_copyInfo);
copyFileWorker.Start();
//wait for the two threads to finish
WorkerThreadBase.WaitAll(copyFileWorker, dummyWorker);
文本轉化為.NET字符串
Management Studio的源代碼包中提供幾個基礎的功能,比如這里的將字符串轉化為.NET代碼的功能。這個功能的源代碼來自網友的代碼,當時覺得很有用一直收藏着。
曾經有一段時間發現.NET的字符串前綴轉義標識@支持換行,參考下面的代碼例子,@符號支持多行文本。
private string test = @" [assembly: AssemblyCopyright(Copyright © 2015)]
[assembly: AssemblyTrademark()]
[assembly: AssemblyCulture()]";
中文繁體簡體轉換
使用Microsoft.VisualBasic程序集中的方法,一步代碼調用實現簡體轉化為繁體,參考下面的方法代碼。
public string Convert(string s)
{
return (Microsoft.VisualBasic.Strings.StrConv(s as string, Microsoft.VisualBasic.VbStrConv.TraditionalChinese, 0));
}
異常處理
凡是WinForms程序,應該在你的程度開頭增加下面的幾行代碼以實現異常處理,將系統拋出的異常轉化給當前程序處理,並提供友好的界面顯示異常。
CustomExceptionHandler eh = new CustomExceptionHandler();
Application.ThreadException += new ThreadExceptionEventHandler(eh.OnThreadException);
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
Management Studio源代碼下載:http://files.cnblogs.com/files/JamesLi2015/ManagementStudio.zip