通過增強的 Windows Forms 支持爲 .NET 應用程序精心製作華麗的 UI

本文將介紹以下內容:

Windows Forms 控件的新增功能

設置和資源管理

佈局、調整大小和縮放

數據綁定

ClickOnce 部署

本文涉及以下技術:
Windows Forms、Visual Studio、.NET Framework 2.0

*
本頁內容
Windows Forms 項目 Windows Forms 項目
代碼分離 代碼分離
改進的資源管理 改進的資源管理
改進的設置管理 改進的設置管理
System.Windows.Forms.Form System.Windows.Forms.Form
捕捉線、邊距和填充 捕捉線、邊距和填充
自動調整大小和縮放 自動調整大小和縮放
TableLayoutPanel 和 FlowLayoutPanel TableLayoutPanel 和 FlowLayoutPanel
控件和組件 控件和組件
MaskedTextBox 控件 MaskedTextBox 控件
Web 瀏覽器 Web 瀏覽器
BackgroundWorker 組件 BackgroundWorker 組件
自動完成 自動完成
條形控件 條形控件
條形容器 條形容器
數據綁定 數據綁定
BindingSource BindingSource
DataGridView DataGridView
拖放式數據綁定 拖放式數據綁定
ClickOnce 部署 ClickOnce 部署
發佈 發佈
安全性 安全性
總結 總結

Windows Forms 2.0 比它之前的任何 Windows 應用程序開發平臺的功能都要豐富得多。您將會發現全方位的改進:採用更爲緊湊的全功能 Microsoft® .NET Framework、Visual Studio® 與許多新的附加設計器的集成更爲緊密、採用統一的數據綁定模型以及錦上添花的 ClickOnce Web 樣式部署。

System.Windows.Forms 命名空間(構成 Windows® Forms 之技術的核心)得到了顯著改進。命名空間(由公共類型(類和枚舉)組成)的可使用表面區域比 .NET Framework 1.1 增加了約 134%。新增了 446 種公共類型;113 個現有類型使用新成員和新值進行了更新;原有命名空間中的 218 種類型得到了保留;而且沒有刪除任何類型。這是一次覆蓋範圍很廣的發佈。事實上,其覆蓋範圍廣到我們沒有足夠的篇幅來做全面介紹。不過,圖 1 可以讓您有一個大致的瞭解。功能可真是不少!它們都等着您在創建新的 Windows Forms 項目時將它們派上用場。

Windows Forms 項目


圖 2 Windows Forms 項目結構

無論您偏好使用 C# 還是 Visual Basic®,創建新 Windows Forms 項目時首先引起您注意的都將是 Visual Studio Windows 應用程序項目嚮導生成的新默認項目結構,如圖 2 所示。更新的結構具有若干個項目增強功能,我們將對這些功能進行介紹。

代碼分離

新默認項目結構的一個目標是從默認 Form1 中刪除代碼。如果使用的是 C#,裁減後所得到的實施代碼與以下內容類似:

// Form1.cs
partial class Form1 :Form {
public Form1() {
InitializeComponent();
  }
}

Visual Basic 在代碼裁減操作上花費的時間會略長:

' Form1.vb
Public Class Form1
End Class

您可能想知道 InitializeComponent 到哪裏去了。在 Windows Forms 2.0 中,設計人員管理的窗體代碼(如 InitializeComponent 方法)保留在新文件 FormName.Designer.cs 或 FormName.Designer.vb 中。這種分離旨在避免開發人員與 Windows Forms 設計人員之間發生爭執,在 C# 和 Visual Basic 中可以通過爲 partial class 提供新語言支持來啓用該功能,如下面的示例代碼所示:

// Form1.cs(開發人員管理的)
public partial class Form1 :Form { ... }

// Form1.Designer.cs(設計人員管理的)
partial class Form1 {
    ...
void InitializeComponent() { ... }
    ...
} 

下面是起同樣作用的 Visual Basic 代碼:

' Form1.vb(開發人員管理的)
Public Class Form1
End Class

' Form1.Designer.vb(設計人員管理的)
Partial Class Form1
Inherits System.Windows.Forms.Form
    ...
Private Sub InitializeComponent()
        ...
End Sub
    ...
End Class

如果您是 C# 開發人員,可能也想知道嚮導生成的靜態 Main 方法到哪裏去了。因爲 Main 的作用域是應用程序而不是窗體,所以它已經被移動到其自己的文件 Program.cs 中:

// Program.cs
static class Program {
/// <summary>
/// 應用程序的主要入口點。
/// </summary>
[STAThread]
static void Main() { ... }
}

默認情況下 Visual Basic 項目配置爲在應用程序啓動時即啓動 Form1。必要時可以使用自定義 Shared Sub Main 入口點。代碼分離的結果是,開發人員可以集中精力只編寫解決其特定問題所需的代碼。

改進的資源管理

IDE 本身進行了更新,以簡化 Windows Forms 2.0 編程。Visual Studio 資源編輯器得到了急需的改進,所帶來的主要益處是提高了管理和查看資源實際外觀的能力,如圖 3 所示。


圖 3 Visual Studio 資源編輯器

現在,在資源編輯器中可以通過多種機制添加新文件和現有文件,其中包括圖 3 所示的下拉列表、從“剪貼板”粘貼和拖放操作。無論採用何種機制,資源都會自動歸入下列類別之一:Strings(字符串)、Images(圖像)、Icons(圖標)、Text Files(文本文件)和 Sound Files(聲音文件)。還有一個類別 Other(其他),用於像組件定義的設計時數據序列化這樣的資源數據。要查看每個類別,請選擇資源編輯器左上方的下拉列表。每個類別都會根據它所包含的資源類型進行調整來提供專門的視圖。例如,您可以通過 Details(詳細資料)、List(列表)或 Thumbnail(縮略圖)視圖來查看字符串以外的所有資源類型,就像在 Windows 資源管理器中那樣。

另一項重要改進就是提供了指定資源是嵌入資源還是鏈接資源的功能。通過屬性編輯器添加到項目中的嵌入資源存儲在項目範圍資源 (.resx) 文件中。鏈接資源(字符串以外資源的默認設置)表示 Visual Studio 引用項目系統外部的文件,這使不同的人可以更方便地管理資源數據(所需的圖形和聲音數據),同時開發人員又可以從事他們最擅長的工作:創建應用程序。Visual Studio 在這一方面也爲開發人員提供了便利。

設想一下以前在使用 Windows Forms 1.x 時從代碼中檢索字符串資源所需執行的步驟:

// 加載項目資源文件中的字符串資源
Assembly assem = Assembly.GetExecutingAssembly();
ResourceManager resman = new ResourceManager("MyApp.Resource1", assem);
string myStringResource = resman.GetString("MyString");

再設想一下采用 Windows Forms 2.0 所支持的簡化強類型化方法時所需執行的步驟:

// 加載強類型化字符串資源
string myString = Properties.Resources.MyString;

Windows Forms 此時生成了類 Resources(位於 ProjectName.Properties 命名空間內),它通過強類型化靜態(共享)屬性來提供每個資源。現在,對於代碼中包括圖標、圖像和聲音在內的任何資源類型,都可以輕鬆地將它們作爲字符串進行檢索:

// 所有類型的強類型化資源
string myString = Properties.Resources.MyString;
Icon myIcon = Properties.Resources.MyIcon;
Image myImage = Properties.Resources.MyImage;
UnmanagedMemoryStream mySound = Properties.Resources.MySound;

再向項目中添加其他 .resx 文件時,也會導致生成強類型化包裝類。

改進的設置管理

項目屬性頁上提供了一個新的 Settings Editor(設置編輯器),可以通過它向下列兩個作用域之一添加設置:應用程序和用戶。應用程序設置(如數據庫連接字符串和 URL)是永久性設置,應用程序安裝後便不會更改。用戶設置(如 Tools(工具)| Options(選項)菜單中的設置)是一些默認設置,用戶可以在安裝後進行更改。圖 4 顯示了運行中的 Settings Editor(設置編輯器)。


圖 4 Visual Studio Settings Editor(設置編輯器)

Settings Editor(設置編輯器)通過應用程序的配置文件 (ApplicationName.exe.config) 來部署應用程序設置和用戶設置。與資源類似,Windows Forms 也會生成強類型化包裝類(位於 ProjectName.Properties 命名空間內)。應用程序設置作爲只讀屬性來實現,而用戶設置則作爲讀/寫屬性來實現。二者都可以通過生成的靜態(共享)Default 屬性以編程方式進行檢查或更新:

// 檢查以應用程序爲作用域的設置
string myAppSetting = Properties.Settings.Default.MyApplicationSetting;

// 更新以用戶爲作用域的設置
Properties.Settings.Default.MyUserSetting = "myNewUserSettingValue";

由於用戶希望他們對設置進行的更改能夠從一個應用程序會話延續到下一個會話,因此需要在一個會話結束時保存更改後的用戶設置,並在另一個會話開始時重新加載該設置。儘管在每個會話開始時用戶設置和應用程序設置會自動加載,但必須在會話結束時通過調用 Save 方法來手動保存用戶設置,該方法由生成的 Settings 類提供,如下所示:

void OptionsForm_FormClosing(object sender, FormClosingEventArgs e) {
// 保存用戶設置以供下一次使用
Properties.Settings.Default.Save();
}

應用程序設置是隻讀的,用戶設置則不是,而且將其保存到的文件不能是應用程序配置文件。因此,Windows Forms 會將用戶設置保存到 user.config,它位於與用戶綁定的 Windows 兼容文件系統位置。該文件的路徑會視某些條件(如是否啓動了漫遊)而異。下面的位置由獨立應用程序使用:

%InstallRoot%/Documents and Settings/UserName/
Local Settings/Application Data/ProductName/
ApplicationName.exe_Url_UrlHash/AssemblyVersionNumber

有時用戶將設置更改爲他們並不想要的值,但已經記不清先前的設置了。在這種情況下,可以通過調用 Settings 對象的 Reload 方法來提供恢復爲最後保存設置的機制:

void reloadSettingsButton_Click(object sender, EventArgs e) {
// 恢復爲最後保存的用戶設置
Properties.Settings.Default.Reload();
}

其次,如果用戶設置被完全覆蓋,可以恢復到應用程序最初部署的設置:即在 Settings Editor(設置編輯器)中輸入的值。恢復這些值需要調用 Settings 對象的 Reset 方法:

void resetButton_Click(object sender, EventArgs e) {
// 恢復爲安裝時的默認用戶設置
Properties.Settings.Default.Reset();
}

用戶設置採用下面這種方式來管理:如果刪除 user.config 文件,這些設置的默認值將加載到下一個應用程序會話中。

System.Windows.Forms.Form

Visual Studio 是用來構建 Windows Forms 應用程序的最重要工具,System.Windows.Forms.Form 則是最重要的類。正如您所期待的那樣,此類進行了更新,現在添加了一些重要的新成員,圖 5 中列出了這些新成員。到目前爲止,新成員中最值得關注是那些與佈局有關的部分。

捕捉線、邊距和填充

將控件拖動到窗體上並將它們四處拖動時,可以使用捕捉線來對齊控件。將控件拖動到窗體上時,捕捉線顯示爲一條或多條粘性線,它們會引導控件與其他控件在水平和垂直兩個方向上都緊鄰共用文本基線和文本邊距的地方對齊(請參閱圖 6)。


圖 6 捕捉線

除相互對齊外,控件彼此間還需保持合理的間距。儘管捕捉線不能滿足調整間距的需要,但控件上提供的兩個新屬性卻可以做到:填充和邊距。填充是指從窗體或控件工作區邊緣算起、子控件(以及文本和圖像等)不能強行進入的內部距離(像素)。邊距是指從控件邊緣算起、其他控件不能強行進入的外部距離。拖動控件時,如果控件與窗體間的距離是其邊距與填充之和,則會在控件和窗體之間顯示一條藍線。圖 7 顯示了用來確定何時控件具有正確間距的邊距和填充。可以一次指定所有邊緣的填充和邊距屬性,也可以分別指定各邊緣的填充和邊距屬性。


圖 7 邊距和填充的使用

自動調整大小和縮放

由於捕捉線、邊距和填充只是一些輔助線,因此可能會被忽略,這就可能導致在移動控件或調整控件大小時,控件會被部分或完全隱藏。您將需要調整容器控件大小來顯示調整了大小或進行了移動的控件的隱藏部分,如果涉及許多控件,就會成爲一項枯燥乏味的工作。實際上可以使用 AutoSize 和 AutoSizeMode 屬性來完成這項工作。AutoSize 是一種布爾屬性,設置爲 true 時,將會指示控件自動調整大小來適應其內容。AutoSizeMode 屬性會指示控件如何調整大小,即按照 AutoSizeMode (System.Windows.Forms) 枚舉的 GrowOnly 和 GrowAndShrink 值的指定調整大小。

GrowOnly 指定如果容器所包含控件的新尺寸等於或大於原尺寸,容器應自動調整大小。GrowAndShrink 指定容器應增大或減小尺寸來響應所包含控件的大小調整和移動,如圖 8 所示。


圖 8 使用 GrowAndShrink 自動調整大小

當控件邊緣與宿主容器右邊緣和底邊緣(它們的邊距重疊區)靠得足夠近時,將會觸發自動大小調整。有多種控件都支持僅使用 AutoSize,或同時使用 AutoSize 和 AutoSizeMode。有一些控件(如窗體)確實實現了這兩個屬性,但只會在運行時使用它們。您將需要試着使用每一個控件,才能確定其自動調整大小支持的程度。

除了可以自動調整大小來適應內容外,窗體和控件還可以在所有 DPI 設置中自動調整大小,同時保持尺寸和位置比例不變。要在多個 DPI 設置中保持相同的比例(或稱縮放),需要兩個重要元素。第一個元素指示窗體進行自動縮放。第二個元素指示窗體對窗體及其控件的尺寸和位置應用什麼縮放係數。默認情況下,窗體通過其 AutoScale 屬性(設置爲 true)進行自動縮放。縮放係數由 AutoScaleMode 屬性指定,其值可以是下列值之一:

enum AutoScaleMode {
None = 0, // 不縮放
Font = 1, // 根據字體大小縮放(默認值)
Dpi = 2, // 根據 dpi 縮放
Inherit = 3 // 繼承容器的 AutoScaleMode
}

默認值爲 Font,表示縮放係數是以窗體創建和執行窗體時默認系統字體平均寬度和高度的比率爲基礎的。例如,如果在 Windows XP 常規字體 (96 DPI) 下創建窗體,默認字體將爲 8.25pt MS Sans Serif,平均寬度和高度爲 6x13。此信息由 Windows 窗體設計器自動存儲在窗體的 AutoScaleDimensions 屬性中:

// AutoScalingForm.designer.cs 
partial class AutoScalingForm {
    ...
void InitializeComponent() {
        ...
this.AutoScaleDimensions = new SizeF(6F, 13F);
        ...
    }
}

如果後來在默認字體爲 7.8pt MS Sans Serif 的大字體 (120 DPI) 下重新打開窗體或執行窗體,字體的平均寬度和高度將增加到 8x16。窗體會注意到 AutoScaleDimensions 與當前縮放尺寸之間的差異,然後根據計算的差異來調整其控件的寬度、高度和位置。這樣一來,無論系統字體怎樣設置,都可使窗體的總體外觀保持大致相同。在 Visual Studio 內部同一行爲也將保持一致。

AutoSizeMode.Font 使縮放以各 DPI 之間的字體差異爲基礎,AutoSizeMode.Dpi 則使縮放完全以各 DPI 之間的差異爲基礎。圖 9 對這兩種模式做了比較。


圖 9 從 96 DPI 自動縮放到 120 DPI

AutoScaleMode.Font 和 AutoScaleMode.Dpi 之間在實際使用時的區別是,前後兩者的縮放率不同,因爲成比例字體的縮放方式不同於純線性的 DPI 縮放,這一點在不同語言的縮放上體現的尤爲明顯。AutoScaleMode.Font 是默認選項,因爲它是最可靠的選項。

TableLayoutPanel 和 FlowLayoutPanel

儘管捕捉線、邊距、填充、自動調整大小和自動縮放組成了一個有用的佈局工具箱,但它們無法方便地支持可調整大小對話框中包含相當多控件的更復雜情況。由於對此類情況有所預見,Windows Forms 加入了兩個新的佈局控件:TableLayoutPanel 和 FlowLayoutPanel。

TableLayoutPanel 支持 HTML 樣式表佈局。可以通過下列三種方法之一來定義可配置爲自動調整大小的行和列:

自動調整大小:自動調整大小來適應其內容

百分比:大小是 TableLayoutControl 總高度或寬度的百分比

絕對大小:固定大小(像素)

通過 Windows 窗體設計器可以合併行和列及調整它們的大小。每個單元格可以只包含一個控件,其在單元格內的位置隨停靠和定位而變。圖 10 顯示了作用中的 TableLayoutPanel 示例。它還顯示了駐留在嵌套 TableLayoutPanel 內的“確定”和“取消”按鈕;需要在每個單元格中放置多個控件時,嵌套 TableLayoutPanel 是一種很有用的方法。


圖 10 TableLayoutPanel 控件

FlowLayoutPanel 支持 HTML 樣式流佈局。通過將其 FlowDirection 屬性設置爲以下四個值之一,可以指示 FlowLayoutPanel 在調整大小過程中應將包含的控件推向哪個方向:LeftToRight、TopDown、RightToLeft 和 BottomUp。

與處理 Web 頁時相同,調整 FlowLayoutPanel 大小時也可以使其包含的控件完全無法再進行移動,從而使這些控件部分或全部爲 FlowLayoutPanel 的垂直和/或水平邊緣覆蓋。在這些情況下,可以根據需要將 AutoScroll 屬性設置爲 true,以提供垂直和水平滾動條。

控件和組件

Windows Forms 2.0 提供了一整套以填補先前工具箱漏洞爲主要目標的新控件和組件,其中包括 MaskedTextBox、WebBrowser 和 BackgroundWorker。此外,控件和組件庫也進行了各種全方位的改進,其中包括使常用控件以實時方式在外觀上適應當前 Windows 主題的功能,以及支持在設計器中使用智能標記來使開發者能夠更快速、更集中精力地完成配置。

MaskedTextBox 控件

MaskedTextBox 控件是爲了使數據輸入更有依據、更爲準確而設計的,它會就需要使用掩碼輸入的數據類型和形式給出提示,引導用戶完成輸入(請參閱圖 11)。有許多掩碼字符;如果在構建和測試掩碼時需要幫助,請從 Properties(屬性)窗口打開 MaskedTextBox 控件的 Input Mask Editor(輸入掩碼編輯器)。


圖 12 MaskedTextBox

默認情況下,非掩碼字符(如括號、連字符和空格)均視爲文字,將在運行時顯示以描述所需數據的形式,而所有掩碼字符在運行時將由提示字符替換(默認情況下爲下劃線,僅當焦點位於 MaskedTextBox 上時纔會顯示,如圖 12 所示)。MaskedTextBox 實現了多種屬性,圖 13 中列出了其中最值得注意的一些屬性。MaskedTextBox 是一個可配置性很強的控件,如果想爲用戶提供更有依據的數據輸入體驗,應該考慮使用該控件。

Web 瀏覽器

儘管 Windows Forms 應用程序在任何情況下都可以通過互操作功能使用 COM 控件來支持 Web 瀏覽,但編程體驗略爲凌亂。不過,新的 Web 瀏覽器控件提供了一種有條理的方式來輕鬆地爲 Windows Forms 應用程序增加 Web 瀏覽功能,如圖 14 所示。


圖 14 作用中的 WebBrowser 控件

導航到 URL 就像調用 WebBrowser 的 Navigate 方法那樣簡單:

void goButton_Click(object sender, EventArgs e) {
// 導航到 URL
this.webBrowser.Navigate(this.urlTextBox.Text);
}

當 WebControl 導航到新頁面時,它會先激發 Navigated 事件,然後再開始下載頁面。WebControl 還會激發 ProgressChanged 事件,通過該事件可以監控頁面下載進度。當然,WebBrowser 還提供了可以處理任何瀏覽器中都會提供的若干標準導航選項的方法:

this.webBrowser.GoBack();    // 導航到歷史記錄中的上一頁面
this.webBrowser.GoForward(); // 導航到歷史記錄中的下一頁面
this.webBrowser.Stop();      // 停止加載當前頁面
this.webBrowser.Refresh();   // 重新加載當前頁面
this.webBrowser.GoHome();    // 導航到主頁

BackgroundWorker 組件

Windows Forms 應用程序經常需要執行長時間的後臺操作(如搜索)。其解決方案是在 .NET 中使用多線程支持來衍生一些工作線程,通過異步方式來執行長時間運行的操作,這樣主 UI 線程可以繼續響應用戶請求。但爲工作線程編寫代碼可能是一項艱鉅而又耗時的工作。

不過,在 Windows Forms 2.0 中,可以使用 BackgroundWorker,它將複雜的工作線程創建和管理整合在一個組件中,可以將其拖動到 Visual Studio 中的窗體上。調用 BackgroundWorker.RunWorkerAsync 會導致工作線程引發 BackgroundWorker.DoWork 事件,可以通過處理該事件來執行長時間運行的操作代碼。圖 15 中的代碼顯示了 RunWorkerAsync 和 DoWork。

BackgroundWorker 可確保在 UI 和工作線程間傳遞的數據以線程安全的方式進行。BackgroundWorker 也支持進度報告和取消,並且由於其爲組件,因此可以通過設計器配置此功能。

自動完成

有一項改進是在若干個控件上進行的,那就是自動完成。ComboBox、TextBox、ToolStripComboBox 和 ToolStripTextBox 上都實現了這項改進。它由下面三個屬性組成:AutoCompleteMode、AutoCompleteSource 和 AutoCompleteCustomSource。通過使用 AutoCompleteMode,可以設置同名枚舉的自動完成樣式:

enum AutoCompleteMode {
None = 0,         // 不自動完成(默認值)
Suggest = 1,      // 可能的匹配項從下拉列表中選擇
Append = 2,       // 可能的匹配項附加在所鍵入文本後面
SuggestAppend = 3 // AutoSuggest 和 AutoAppend 相結合
}

除“None”選項外,其餘選項均要求將 AutoCompleteSource 屬性設置爲 AutoCompleteSource 枚舉所指定的幾個系統自動完成來源之一:

enum AutoCompleteSource {
FileSystem = 1,       // 文件系統
HistoryList = 2,      // 歷史記錄列表中的所有 URL
RecentlyUsedList = 4  // 最近使用列表中的所有 URL
AllUrl = 6,           // HistoryList + RecentlyUsedList
AllSystemSources = 7, // FileSystem + AllURL
FileSystemDirectories = 0x20, // 文件系統文件夾
CustomSource = 0x40,  // AutoCompleteCustomSource
None = 0x80,          // 無來源(默認值)
ListItems = 0x100     // 控件列表(僅限組合框)中的項目
}

如果選擇 CustomSource,即是指示 ComboBox 您將通過存儲在 AutoCompleteCustomSource 屬性中的項目集合提供自動完成選項。ListItems 將來源指定爲存儲在 ComboBox List 屬性中的項目。

條形控件

值得特別提及的是條形控件,這是因爲它們有着酷炫的外形。MenuStrip、ToolStrip、StatusStrip 和 ContextMenuStrip 爲用戶界面增添了一股現代氣息,如圖 16 中所示。


圖 16 條形控件

新條形控件接替了 MainMenu、ToolBar、StatusBar 和 ContextMenu(在 Windows Forms 2.0 中得到了保留,以保持向後兼容性),並在它們的基礎上進行了若干個方面的改進,其中包括:

所有條形控件使用一致的 API

改進了設計時體驗

可以在窗體邊緣之間拖動

具有 Office 2003 和 Windows 主題相關性

可以駐留一組豐富的子控件,其中包括下拉列表、標籤、菜單和文本框

簡化了自定義繪製支持

與設置系統集成

與 MainMenuStrip 屬性進行了窗體集成,與 ContextMenuStrip 屬性進行了控件集成

條形控件提供了大規模的設計時支持,其中最重要的支持是簡化了向每個條形控件添加項目的過程。可以添加到條形控件中的項目取決於條形控件的用途,如圖 17 所示。

可以通過 Properties(屬性)窗口使用智能標記來添加、更新和刪除條形控件項目,也可以通過設計圖面直觀地添加、更新和刪除條形控件項目。MenuStrip 和 ToolStrip 都提供了“Insert Standard Items(插入標準項目)”選項,以使用“打開”、“保存”、“另存爲”、“剪切”、“複製”和“粘貼”這類典型命令所對應的項目預填充控件。

通過條形控件 Properties(屬性)窗口和智能標記,可以進行各種其他值得注意的配置,其中最重要的配置由圖 18 中所列的屬性來控制。除了通常可以在控件上看到的標準屬性(如 Enabled、Visible、Checked 和 BorderStyle)外,條形控件還提供了一些附加屬性,如圖 19 所示。

條形容器

條形控件套件的主要特色之一是,可以將條形控件從窗體的一個邊緣拖動到另一個邊緣。儘管默認情況下條形控件停靠在窗體邊緣,但停靠並不提供支持拖動所需的智能。這種行爲實際上是通過 ToolStripContainer 控件添加到窗體中,如圖 20 所示。


圖 20 ToolStripContainer 控件

因爲 ToolStripContainer 是一種提供窗體範圍條形控件語義的容器控件,所以需要在添加任何其他控件之前先將它添加到窗體中。控件隨後將添加到其內容面板,而條形控件將添加到四個特殊面板中的一個。可以展開或摺疊每個面板,以適應您想要放置在各窗體邊緣的條形控件。通過設置 ToolStripContainer 的 TopToolStripPanelVisible、RightToolStripPanelVisible、BottomToolStripPanelVisible 和 LeftToolStripPanelVisible 布爾屬性,還可以根據需要隱藏/顯示面板。

運行時,可以在窗體的邊緣之間拖動條形控件,其對應的面板會顯示出來。只可以拖動具有拖動柄的條形控件。而且,如果有兩個或更多個工具條形控件位於同一工具條形面板中,用戶可以根據需要調整這些控件的位置。因爲用戶可以在運行時將工具條移動到新位置,所以用戶希望在結束一個應用程序會話並啓動下一個應用程序會話時,工具條仍在那些位置。因此,需要使用 ToolStripManager 類(來自 System.Windows.Forms),該類很好地實現了靜態(共享)LoadSettings 和 SaveSettings 方法。

數據綁定

在 Windows Forms 2.0 中,由於新 BindingSource 組件的主要作用是升級不具有數據綁定功能的數據源,使其具有更豐富的數據綁定功能,因此數據綁定功能比以前豐富得多。這樣就可以統一異構數據源,還可以簡化針對任何類型數據源創建單一客戶端代碼模式的過程。


圖 21 數據源

通過使用 Data Source Configuration Wizard(數據源配置嚮導)(Data(數據)| Add New Data Source(添加新數據源)),可以輕鬆地將數據源添加到項目中。可以在其中爲數據庫、Web 服務和對象創建數據源。如果通過數據庫創建數據源,新的強類型化 DataSet 將添加到項目中,並可以通過新的 Data Sources(數據源)窗口(Tools(工具)| Data(數據)| Show Data Sources(顯示數據源))查看它,如圖 21 所示。

Data Sources(數據源)窗口提供了用於添加新數據源的工具條項目,如果數據源是強類型化 DataSet,則還會提供用於編輯、重新配置或刷新它們的工具條項目。拖放到窗體上時,像 DataGridView 這樣的控件將自動提示您選擇數據源或創建一個新數據源。

BindingSource

提到“數據源”,您想到的可能是最常見的類型:類型化 DataSet。但數據源的形式和大小多種多樣,其中包括表、XML 和基於 .NET 的對象。在 Windows Forms 1.x 中,可以綁定到所有上述數據源,但數據綁定集成的程度有差異。這使開發人員不得不花費不少的時間來更新其數據源,以通過實現 IBindingList 來達到更高程度的數據源綁定集成。Windows Forms 2.0 BindingSource 組件解決了這一問題,它能夠使用任何列表類型並將這些類型作爲 IBindingList 列表數據源實現來重新提供。此外,還可以將項目類型傳遞給 BindingSource 組件,該組件會自動將這些項目類型轉換爲 IBindingList 實現。

要配置 BindingSource 以使用所需的數據源,請將一個 BindingSource 拖動到窗體上,根據需要設置它的 DataSource 和 DataMember 屬性。以下是使用類型化 DataSet 的 BindingSource 的示例:

public partial class DataBindingForm :Form {
public DataBindingForm() {
        ...
// 使用類型數據集
this.bindingSource.DataSource = this.northwindDataSet;
this.bindingSource.DataMember = "Employees";
    }
}

BindingSource 組件此時提供強類型化 DataSet 作爲控件可以綁定到的數據源。

DataGridView

Windows Forms 團隊藉此機會構建了一個全新的網格控件 System.Windows.Forms.DataGridView,以響應開發人員社區關於 DataGrid 的反饋。(DataGrid 得到保留,用於導航和編輯分層數據。)

DataGrid 與 DataGridView 之間的一個顯著差異是後者的對象模型,該模型在進行抽象化處理後成爲了由列、行和單元格組成的自然網格結構,如圖 22 所示。開發人員通過這個自然網格結構可以快速地按照邏輯關係深入瞭解衆多位於直觀位置的功能,其中包括:

通過樣式、格式設置、佈局和項目選擇支持豐富的 UI 自定義

原生顯示比 DataGrid 範圍更廣的各種數據類型(包括圖像)的功能

諸如列凍結和運行時列重新排序等一流功能

100 多個事件,用於精確控制導航、編輯、驗證、自定義繪製和錯誤處理


圖 22 DataGridView 對象模型

其中一個新功能是單擊單元格時選擇行,該功能通過 DataGridView 的 SelectionMode 屬性來配置。當然,沒有任何控件可以滿足所有人的任何需要。有這種需要時,開發人員可以依靠擴展功能來引入自定義功能。DataGridView 基礎結構提供了可以作爲派生來源和插件的各種單元格、行和列基本實現,其中包括 DataGridViewColumn 和 DataGridViewCell。所有這些都使 DataGridView 成爲了比 DataGrid 吸引力大得多的網格樣式控件。

填充 DataGridView 的最常見方法是將其綁定到數據源,通過將其 DataSource 屬性設置爲 BindingSource 可實現此目的,如圖 23 所示。


圖 23 將 DataGridView 綁定到 BindingSource

儘管 DataGridView 顯示了多個項目,但有時每次只需要查看一個項目。在這種情況下,可以同樣輕鬆地將 TextBox 這樣的控件綁定到 BindingSource。但如果需要每次查看一個項目,就需要一種方法能夠讓用戶在各個項目之間導航。這種支持通常由 VCR 樣式的控件提供。您不需要自行創建該控件,而是可以將 BindingNavigator 拖動到窗體上,並將其綁定到您的控件綁定到的同一 BindingSource。BindingNavigator 還提供了當前項目和項目總數的計數信息,並且支持將項目添加到數據源及從數據源刪除項目。

拖放式數據綁定

拖放控件和組件,然後編寫代碼來將它們連接起來似乎與數據綁定能夠提高效率這個觀點相左。實際上並不需要手動拖放,然後配置 UI,而是可以將數據源從 Data Sources(數據源)窗口拖放到窗體上,讓 Windows 窗體設計器爲您創建和配置綁定的 UI。

拖放數據源時,Windows 窗體設計器會執行下列操作:

爲該數據源添加 BindingSource

根據需要添加強類型化 DataSet 和表適配器

添加綁定到 BindingSource 的必需控件,從而爲這些控件提供合理的名稱(DataGridView 列除外)

添加綁定到 BindingSource 的 BindingNavigator

還可以配置放置的數據源創建 DataGridView-UI 還是 Details-UI,以及在這兩種情況下生成哪些控件來滿足需要。

ClickOnce 部署

最後,應用程序需要進行部署。儘管安裝應用程序或 Microsoft Installer (MSI) 文件都是不錯的部署技術,但需要將它們分配到客戶端上並要在客戶端上執行它們,並且需要使完成的安裝保持最新狀態。這項工作可能會很艱鉅。Web 應用程序具有一個出色的部署模型:用戶不必執行任何操作就可使應用程序始終是最新版本。

優良的技術會借鑑其他技術的長處;出色的技術則會用心地巧取其精髓。Windows Forms 1.x 採用了稱爲“無觸式部署”(NTD) 的技術,該技術借鑑了 Web 部署模型的優點,可以通過它從 URL 或 UNC 文件路徑部署 Windows Forms 應用程序,並且可以在受代碼訪問安全性 (CAS) 控制的客戶機上的沙箱內執行應用程序。在 Windows Forms 2.0 中,NTD 已經發展成爲 ClickOnce 部署,從而能夠爲 Windows Forms 應用程序提供 Web 樣式部署模型。ClickOnce 提供了下列功能:

•涵蓋已部署應用程序創建、發佈和管理的豐富配置功能

具有多個發佈位置,包括 Web 服務器、FTP 服務器、文件共享以及 CD 和 DVD 這樣的媒體

超鏈接樣式應用程序啓動

兩種安裝模式:聯機和聯機/脫機;在後一種模式下,在用戶機器上緩存 ClickOnce 應用程序後,不需要建立網絡連接就可以啓動該應用程序

控制與客戶端(包括“開始”菜單以及“添加/刪除程序”控制面板)集成的程度

選擇安裝的必備軟件,如 .NET Framework 2.0(通過 Prerequisites(必備軟件)按鈕)

文件和程序集依賴關係管理

設置各種發佈詳細信息(包括髮布者詳細信息)、支持 Web 頁和部署 Web 頁,ClickOnce 可以自動生成這些內容

使用發佈版本號,可以創建針對各種方案的版本控制策略

圍繞代碼簽署構建的可靠的部署和執行模型,以及完全用戶驅動的 CAS

與 Visual Studio 完整集成

設計時,可以在 Visual Studio 中通過項目屬性頁面的 Publish(發佈)選項卡配置 ClickOnce 部署,如圖 24 所示。發佈應用程序時將會應用這些不同配置的集合。


圖 24 配置 ClickOnce 部署

發佈

發佈應用程序的最簡單方法是:在 Solution Explorer(解決方案資源管理器)中右鍵單擊項目,然後選擇 Publish(發佈),隨即會打開 Publish Wizard(發佈嚮導),向您收集各種詳細信息,其中包括髮布位置和安裝模式。

發佈應用程序時,Visual Studio 和 ClickOnce 會根據您的配置準備安裝軟件包,並將其複製到發佈位置。ClickOnce 會生成一個文件夾,其名稱是應用程序名稱與發佈的版本號的結合體。該文件夾包含主要應用程序程序集及任何其他依賴的文件。發佈到具有不允許上載常見可執行文件類型(.exe、.dll)策略的 Web 服務器時,每個文件都將添加後綴“.deploy”。爲存儲構成安裝軟件包的文件,ClickOnce 會生成一個應用程序清單 (.manifest),該清單也會收集您在 Visual Studio 進行的各種配置。

因爲可能存在多個已發佈應用程序版本,所以用戶需要一種方法來確定要下載的版本。出於這一目的,ClickOnce 會生成一個部署清單 (.application) 並將其添加到已發佈應用程序的根目錄,如圖 25 所示。


圖 25 ClickOnce 已發佈應用程序

將會生成兩個部署清單,一個用於最新發布的版本,另一個用於特定版本。在根目錄下,將會創建一個安裝應用程序,供用戶在缺少任何必備軟件(如 .NET Framework 2.0)時執行,並會創建一個默認 Web 頁,用戶可以瀏覽到該 Web 頁並通過它啓動已發佈應用程序。要啓動應用程序,用戶可以單擊 Install(安裝)按鈕,該按鈕是最新版本應用程序清單的超鏈接。

安全性

啓動應用程序後,ClickOnce 首先會下載清單,以確定是否可以在無需用戶干預的情況下安全地下載和執行應用程序。如果發現安全性問題,將通過 Security Warning(安全警告)對話框指出。如果存在任何安全性問題,用戶可以選擇繼續安裝應用程序或放棄安裝。通過單擊“More Information(詳細信息)”鏈接來查看安全性問題的詳細信息,可以幫助用戶做出決定。

ClickOnce 將其警告分爲四個類別:“發佈者”、“機器訪問權限”、“安裝”和“位置”。“發佈者”是指發佈應用程序的人員。要使 ClickOnce 將發佈者視爲是安全的,該發佈者需要使用 Verisign 這樣的認證機構發放的數字證書來簽署其代碼。可以通過 Visual Studio 中項目屬性頁面的 Signing(簽名)選項卡簽署應用程序。可以通過此選項卡從證書存儲區或文件導入證書、創建測試證書、指定證書到期的時間戳服務器以及簽署或延遲簽署程序集。

“機器訪問權限”是指在客戶機上執行應用程序所需的權限。ClickOnce 應用程序的權限由 .NET CAS 管理,.NET CAS 會將執行中的以 .NET 爲目標的應用程序封裝在一個安全沙箱中,該沙箱只允許將權限授予這些應用程序。當所需權限超出從同一區域(啓動 ClickOnce 應用程序的區域)啓動的應用程序所允許的權限時,ClickOnce 會通過添加標記來發出安全警告。如果用戶選擇安裝的應用程序的權限要求過高,CAS 會將這些權限授予應用程序,這一過程稱作權限升級。可以通過項目屬性頁面的 Security(安全性)選項卡管理應用程序的權限要求,如圖 26 所示。


圖 26 ClickOnce 安全性設置

可以通過 Security(安全性)選項卡指定完全信任或部分信任,如果指定的是後者,則可以手動選擇所需權限的子集,或讓系統自動爲您計算。也可以選擇目標區域的默認權限並根據需要進行更改。可以調試應用程序,就好像是從指定區域部署應用程序並被限定爲只具有指定的權限。

總結

我們介紹了許多內容,瀏覽了 Windows Forms 2.0 的一些主要新增功能。對此不感到興奮是困難的,當您想到全年 MSDN®Magazine 的所有版面都不足以詳細介紹所有這些新功能時,就更是如此。不過,我們向您介紹了內容更豐富而且功能更強大的 .NET Framework、新的控件和組件、改進的數據綁定、ClickOnce 部署以及與 Visual Studio 的豐富集成,這些內容無疑很適合作爲您着手研究的對象。熟悉 Windows Forms 2.0 之後,您就會發現可以在比以往都要短的時間內構建具有更多功能的 Windows Froms 應用程序,Windows Forms 2.0 所採用的技術在未來的許多年中都將是旗艦 Windows 應用程序開發平臺。

Chris Sells 是 Microsoft 連通系統部門的程序經理,從事下一代應用程序開發技術的研究工作。可以在 http://www.sellsbrothers.com/ 中找到有關 Chris 和他參與的各個項目的詳細信息。

Michael Weinhardt 目前正在與他人合作更新 Windows Forms Programming in C#(作者:Chris Sells,Addison-Wesley Professional 2003 年出版),併爲稱作 Wonders of Windows Forms 的 MSDN Online 編寫每月專欄文章。有關詳細信息,請訪問 http://www.mikedub.net/

本文摘自 MSDN MagazineVisual Studio 2005 指導教程一期。

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章