使用Component編程是一項值得推崇的技術,它既具有可視化的界面編程模式,又不向UserControl那樣體積龐大。但是,熟悉UserControl的朋友們都知道,在UserControl類中有一個FindForm()函數,返回UserControl所在的窗體的引用,這將大大方便我們對窗體的控制----盡管這可能有些越俎代庖的味道,但有時我們就需要這種控制能力。
但是,在Component並沒有提供這樣的函數,你可以使用其它的一些技巧來取得Component所在的窗體的引用,比如在Component的構造函數中使用Application.AddMessageFilter(this),然後取出由窗體發來的消息的句柄,就可以得到窗體的引用,缺點是不能設計時刻就獲得窗體引用;比如可以給Component加一個StyleForm的屬性,然後你就可以在設計器中用鼠標選擇一個,缺點是你必須手動來選擇。
今天,花了半天的時間,終於設計出了克服了以上兩個缺點的方案,代碼如下:
- using System;
- using System.ComponentModel;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Text;
- using System.ComponentModel.Design;
- using System.Windows.Forms;
- namespace FindFormSimulation
- {
- public partial class BaseStyle : Component
- {
- public BaseStyle()
- {
- InitializeComponent();
- }
- public BaseStyle(IContainer container)
- {
- container.Add(this);
- InitializeComponent();
- }
- /**//// <summary>
- /// 關鍵在這裡,對基類的Site重載。
- /// </summary>
- public override ISite Site
- {
- get
- {
- return base.Site;
- }
- set
- {
- if (base.Site != value)
- {
- base.Site = value;
- //使用反射機制,在設計時刻取得你要控制的窗體。
- IReferenceService referenceService = (IReferenceService)this.GetService(typeof(IReferenceService));
- if (referenceService != null)
- {
- /**////下面這句用於取得本組件所在的窗體對象。
- object[] parent = referenceService.GetReferences(typeof(Form));
- Form container = parent[0] as Form;
- StyleForm = container;
- /**////如下方法測試,可以知道parent.Length總是為1的。
- //StyleForm.Text = parent.Length.ToString();
- }
- }
- }
- }
- private Form styleForm = null;
- [Description("本組件所要控制的窗體"), DefaultValue(null)]
- public Form StyleForm
- {
- get { return styleForm; }
- set
- {
- if (styleForm != value)
- {
- styleForm = value;
- }
- }
- }
- }
- }