C#中窗體之間的資料傳遞 ----尤其是事件那個好好看看

哈哈哈哈哈我撒發表於2009-09-29

對於窗體間的資料傳遞,是剛開始從事.Net窗體應用程式開發人員碰到的一個常見問題,在此講幾個常見的實現方式。此節內容適用於模式窗體或非模式窗體,部分方式延伸到一般類的操作。

(1)建構函式引數傳遞
通過建構函式傳遞引數應該是比較基本的引數傳遞方式,過載建構函式,通過帶引數的建構函式來例項化窗體。
在窗體類內部定義引數變數,
private object myParams;

實現建構函式,
public OptionForm(object parameters)
{
    InitializeComponent();
    this.myParams = parameters;//設定引數引用
}

例項化窗體,
OptionForm form = new OptionForm( myParams );

在實際使用過程中,需要注意傳入的是引用型別還是值型別,處理方式會有所不同。

(2)使用窗體的屬性
說起屬性關聯,上面已經提到過Form.Owner屬性,下面筆者根據MSDN文件來比較完整的講一下,大部分的文字來自MSDN文件,為保證其完整性,對其中一些屬性描述進行了擴充套件。

Form.Owner 屬性。獲取或設定擁有此窗體的窗體。
語法,public Form Owner { get; set; }
若 要使某窗體歸另一個窗體所有,可為其 Owner 屬性分配一個對將成為所有者的窗體的引用。當一個窗體歸另一窗體所有時,它便隨著所有者窗體最小化和關閉。例如,如果 Form2 歸窗體 Form1 所有,則關閉或最小化 Form1 時,Form2 也會關閉或最小化。並且附屬窗體從不顯示在其所有者窗體後面。可以將附屬窗體用於查詢和替換視窗之類的視窗,當選定所有者窗體時,這些視窗不應消失。
Form.OwnedForms 屬性。獲取 Form 物件的陣列,這些物件表示此窗體擁有的所有窗體。
語法,public Form[] OwnedForms { get; }
此 屬性返回包含此窗體擁有的所有窗體的陣列。要使某窗體歸另一個窗體所有,可呼叫 AddOwnedForm 方法。分配給所有者窗體的窗體將保持被擁有狀態,直到呼叫了 RemoveOwnedForm 方法。如果窗體是多文件介面 (MDI) 父窗體,則除了當前開啟的所有 MDI 子窗體外,此屬性將返回所有顯示的窗體。
Form.MdiChildren 屬性。獲取窗體的陣列,這些窗體表示以此窗體作為父級的多文件介面 (MDI) 子窗體。
語法,public Form[] MdiChildren { get; }
此 屬性使您得以獲取對當前在某 MDI 父窗體中開啟的所有 MDI 子窗體的引用。若要建立 MDI 子窗體,請將要成為 MDI 父窗體的 Form 分配給該子窗體的 MdiParent 屬性。可以使用此屬性依次通過所有 MDI 子窗體,以執行一些操作,如當 MDI 父窗體關閉時將資料儲存到資料庫中,或者根據應用程式中執行的操作更新子窗體上的欄位。
Form.MdiParent 屬性。獲取或設定此窗體的當前多文件介面 (MDI) 父窗體。
語法,public Form MdiParent { get; set; }
若要建立 MDI 子窗體,請將要成為 MDI 父窗體的 Form 分配給該子窗體的 MdiParent 屬性。可以從某 MDI 子窗體使用此屬性來獲取所有子窗體都需要的全域性資訊或者呼叫對所有子窗體執行操作的方法。
Form.ActiveForm 靜態屬性。獲取此應用程式的當前活動窗體。
語法,public static Form ActiveForm { get; }
表示當前活動窗體,或者如果沒有活動窗體,則為空引用。可以使用此方法獲得對當前活動窗體的引用,以在該窗體或其控制元件上執行操作。
Form.ActiveMdiChild 屬性。獲取當前活動的多文件介面 (MDI) 子視窗。
語法,public Form ActiveMdiChild { get; }
返 回表示當前活動的 MDI 子視窗的 Form,或者如果當前沒有子視窗,則返回 空引用。可使用此方法確定 MDI 應用程式中是否有任何開啟的 MDI 子窗體。也可使用此方法從 MDI 子視窗的 MDI 父窗體或者從應用程式中顯示的其他窗體對該 MDI 子視窗執行操作。
ContainerControl.ParentForm 屬性。獲取將容器控制元件分配給的窗體。
語法,public Form ParentForm { get; }
將容器控制元件分配給的 Form。

(3)使用公共屬性(念時注:我比較常用這種方式)
使 用公共屬性也是一種比較常用的方式,通過窗體設計器新增的控制元件預設訪問修飾符為private級別,可以設定成public或Internal(在程式集 內部可見)來對外公開。比如對窗體中的Button進行公開,那就可以訪問Button的相關屬性,同時也可以註冊事件或撤銷事件註冊。如,
OptionForm form = new OptionForm();
form.buttonOK.Click += new EventHandler(buttonOK_Click);
form.ShowDialog();

對於只允許讀取訪問或修改訪問的控制元件或變數可以通過屬性來控制。對(1)方式進行修改,去除過載建構函式,增加屬性也可以實現同樣的效果。
public object MyParams
{
    get { return this.myParams;  }
    set { this.myParams = value;  }
}

(4)使用公共方法
使用公共方法類似於屬性,對上面的同等實現如下,
//獲取引數
public object GetParams()
{
    return this.myParams;
}
//設定引數
public void SetParams(object myParams )
{
    this.myParams = myParams;
}

(5)使用靜態類該方式可以簡單的理解為靜態變數全域性共享,通過下面程式碼能夠比較清楚的理解,先來定義靜態類,
public static class ParameterSettings
{
    //公共靜態變數
    public static string Username = "Zhengzuo";
    //私有靜態變數
    private static string userRole = "Administrators";
    //私有靜態變數
    private static string password = "http://blog.csdn.net/zhzuo";
    //內部屬性
    internal static string UserRole
    {
        get { return userRole; }
    }
    //公共屬性
    public static string Password
    {
        get { return password; }
        private set { password = value; }
    }
}

在需要訪問的地方通過以下方式進行,
string username = ParameterSettings.Username;
string password = ParameterSettings.Password;
string userRole = ParameterSettings.UserRole;
ParameterSettings.Username = "鄭佐";//修改成新使用者名稱

(6)窗體實現Singleton模式
Singleton 模式是我們開發過程中最常用的模式之一。在技術社群經常看到有人談及對主窗體實現Singleton,但個人認為這不是一種妥當的做法,因為沒有這個必 要。這裡通過另一個自定義類來進行演示。假設UserLoginInfo類用來儲存登入系統後的使用者憑據。
/*==============================================
程式 鄭佐 2006-4-23 http://blog.csdn.net/zhzuo
==============================================*/
public class UserLoginInfo
{
    //實現Singleton模式,執行緒安全。
    private readonly static UserLoginInfo currentUserInfo = new UserLoginInfo();
    //提供全域性訪問點
    public static UserLoginInfo CurrentUserInfo
    {
        get { return currentUserInfo; }
    }
    //阻止顯式例項化,但不能阻止反射方式呼叫。
    private UserLoginInfo()
    {
    }
    //公共變數
    public string Username;
    //私有變數
    private static string userRole;
    //私有變數
    private static string password;
    //內部屬性
    internal string UserRole
    {
        get { return userRole; }
        set { userRole = value; }
    }
    //公共屬性
    public string Password
    {
        get { return password; }
        internal set { password = value; }
    }
}

在其他程式碼中進行訪問,
UserLoginInfo.CurrentUserInfo.Username ="鄭佐";
UserLoginInfo.CurrentUserInfo.UserRole = "dotnetlover";
UserLoginInfo.CurrentUserInfo.Password = "http://blog.csdn.net/zhzuo";

對於Singleton模式的實現方式有很多,編寫時需要考慮是否需要保證例項訪問的執行緒安全問題,以免引發不可預料的情況,為了提高效能可以考慮惰性例項化。關於Singleton模式的更多資訊可以參考另一篇文章。

(7)釋出事件進行訂閱
通過事件來傳遞引數應該說是一種推的實現方式,在產生事件時進行被動的獲取相關資料。這裡將通過一個自定義事件來演示資料的傳輸。
在自定義事件時,標準的做法都會先定義一個事件引數類,要麼直接使用基類EventArgs,或者從EventArgs繼承實現自己的引數類,假設自定義基類取名為OptionSettingEventArgs,
//選項設定事件引數類
public class OptionSettingEventArgs : EventArgs
{
    private string changedPath;
    //建構函式
    public OptionSettingEventArgs(string changedPath)
    {
        this.changedPath = changedPath;
    }
    //讀取引數
    public string ChangedPath
    {
        get { return this.changedPath; }
    }
}

以上引數類只包含一個修改後的路徑引數。接下去我們要對原先的OptionForm窗體增加事件定義,這裡使用.net 2.0中提供的泛型類來實現。
//定義事件
public event EventHandler<OptionSettingEventArgs> OptionSettingChanged;
編寫事件引發程式如下,
//引發OptionSettingChanged事件
protected virtual void OnOptionSettingChanged(OptionSettingEventArgs e)
{
    if (OptionSettingChanged != null)
    {
        OptionSettingChanged(this, e);
    }
}

對檔案目錄選擇按鈕事件處理程式進行修改來實現事件激發,並沒有考慮直接從文字框直接資料輸入方式。
//通過目錄對話方塊設定新的路徑
private void buttonBrowser_Click(object sender, EventArgs e)
{
    FolderBrowserDialog dialog = new FolderBrowserDialog();
    DialogResult result = dialog.ShowDialog(this);
    if (result == DialogResult.OK)
    {
        if(this.textBoxPath.Text != dialog.SelectedPath)
        {
            this.textBoxPath.Text = dialog.SelectedPath;
            OptionSettingEventArgs args = new OptionSettingEventArgs(dialog.SelectedPath);
            OnOptionSettingChanged(args);
        }
    }
}
好了,一切準備工作完成,呼叫程式碼如下,
OptionForm form = new OptionForm();
//註冊事件
form.OptionSettingChanged += new EventHandler (form_OptionSettingChanged);
form.ShowDialog();
通過以下事件處理程式來驗證其正確性,
private void form_OptionSettingChanged(object sender, OptionSettingEventArgs e)
{
    string newPath = e.ChangedPath;
    MessageBox.Show(this, String.Format("新路徑為“{0}”。", newPath), "提示");
}

不知大家讀了之後覺得怎麼樣,我覺得受益匪淺,感覺講得很仔細,很全面,而且通俗易懂,希望你們也能有同樣的感受。

相關文章