【C#.Net】如何過濾自訂使用者控制項的屬性與事件項目

  • 1313
  • 0
  • 2017-04-05

在建立自訂使用者控制項時,常需要將繼承自UserControl的屬性與事件隱藏,只開放想公開的部分,這裡將示範如何實現此想法。

這邊以MSDN中小時鐘為範例來示範:

1. 新增專案 >> Windows Form 控制項程式庫 >> 名稱:ctrlClockLib。

2. 將 UserControl1命名為 ctrlClock,設定 Size 為 250, 50,設定 BackColor 為 Black,並在其上放置 Label 元件,命名為 lblDisplay,設定 Size 為 240, 40,設定 Location 為 5, 5,並調整,設定 BackColor 為 DimGray,ForeColor 為 Lime,TextAlign 為 MiddleCenter,設定自己喜歡的字型與樣式。

3. 因為我們的重點不再建立 Clock 控制項,所以功能面的部份就不再這裡多作闡述,就以目前的樣子作為範例即可,按下【F6】建置方案,完成後接下來就要測試這個 Clock 控制項囉。

4. 首先,因為控制項不是獨立的應用程式,必須裝載在容器中才能測試,所以我們必須建立一個 Window Form 應用程式來做測試。

5. 按下【檔案】>>【加入】>>【新增專案】>>選擇【Windows Form 應用程式】>>為專案名稱命名為【Test】。

6. 【方案總管】>>【Test】專案 >>【參考】>> 按下滑鼠右鍵選擇【加入參考】。

7. 【方案】>>【專案】>> 勾選【ctrlClockLib】>>【確定】。

8. 【工具箱】>>【ctrlColckLib 元件】>>【ctrlClock】>>點擊滑鼠兩下,將 Clock 控制項增加到剛剛建立的 Windows Form 上。

9. 點擊剛加入的 Clock 控制項,開啟【屬性】檢視視窗,可發現 UserControl 的所有公開屬性皆繼承並顯示出來了。

10. 好了,開始進入重點了,此元件並不須要讓使用者作耴此多的設定,所以我們要將不需要的項目隱藏。

11. ctrlClock 控制項的程式碼應該如下所示:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ctrlClock
{
    public partial class ctlClock: UserControl
    {
        public ctlClock()
        {
            InitializeComponent();
        }
    }
}

12. 於【ctrlClockLib】專案名稱上,點擊滑鼠右鍵,選擇【加入】>>【新增項目】。

13. 選擇【類別】>>>命名為【ctrlClockDesigner.cs】>>【新增】。

14. 將 System.Desigm.dll 加入參考。

15. 為新增的 ctrlClockDesigner 類別加入下方程式碼。

using System;
using System.Linq;
using System.Windows.Forms.Design;

namespace ComponentSet
{
    /// <summary>
    /// 提供CustomUserControl在Design-Time過濾屬性以及事件的類別
    /// </summary>
    [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
    public class JLabelExDesigner : ParentControlDesigner
    {
        /// <summary>
        /// 設定要過濾掉的的屬性
        /// </summary>
        static String[] DisabledProperty = new string[] 
        {
            "AccessibleDescription", "AccessibleName", "AccessibleRole",
            "AllowDrop", "Anchor", "AutoScroll", "AutoScrollMargin", "AutoScrollMinSize",
            "AutoSize", "AutoSizeMode", "AutoValidate", "BackColor", "BackgroundImage",
            "BackgroundImageLayout", "BorderStyle", "CausesValidation", "ContextMenuStrip",
            "Cursor", "Dock", "Enabled", "ForeColor", "ImeMode",
            "Margin", "MaximumSize", "MinimumSize", "Padding", "RightToLeft", 
            "TabIndex", "TabStop", "Tag", "UseWaitCursor", "Visible"
        };

        /// <summary>
        /// 過濾屬性
        /// </summary>
        /// <param name="properties"></param>
        protected override void PreFilterProperties(System.Collections.IDictionary properties)
        {
            //針對UserControl每個屬性進行過濾
            foreach (var pi in typeof(System.Windows.Forms.UserControl).GetProperties())
            {
                if (properties.Contains(pi.Name))
                {
                    if (DisabledProperty.Contains(pi.Name))
                    {
                        properties.Remove(pi.Name);
                    }
                }
            }

            base.PreFilterProperties(properties);
        }

        protected override void PreFilterEvents(System.Collections.IDictionary events)
        {
            //針對UserControl每個事件進行過濾
            foreach (var ei in typeof(System.Windows.Forms.UserControl).GetEvents())
            {
                if (events.Contains(ei.Name))
                    events.Remove(ei.Name);
            }

            base.PreFilterEvents(events);
        }

    }
}

16. 在回到 ctrlClock 控制項的程式碼,於 class 的上方增加一行 [Designer(typeof(ctrlClockDesigner))],程式碼如下所示:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ctrlClock
{
    [Designer(typeof(ctrlClockDesigner))]     //設定那些屬性要在子類別中顯示
    public partial class ctlClock: UserControl
    {
        public ctlClock()
        {
            InitializeComponent();
        }
    }
}

17. 在回到 Windows Form 中來看一下 ctrlClock 控制項,點擊一下控制項並開啟屬性檢視視窗,是否變成如下圖所示了呢?如果是,恭喜你成功了~~~ 落落長的屬性列表不見囉~~