熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

編寫與.NET屬性窗口交互的RAD組件(四)

2013-11-13 10:09:16  來源: .NET編程 

  提供可交互的屬性視圖
  
  當你在Visual C# NET中創建一個項目的時候你可能會注意到屬性窗口的工具欄上有一個像閃電的按鈕按下這個按鈕屬性窗口就會切換到事件視圖這樣就可以來編輯事件處理了
  
  屬性窗口的視圖來自屬性頁(Property Tabs)因此視圖使用的最主要的類是PropertyTab命名空間是SystemWindowsFormsDesign一個屬性頁可以和一個特別的組件設計文檔關聯起來或者是可以使用的靜態關聯和組件或文檔關聯起來的屬性頁在類上用PropertyTabAttribute特性來指定這個特性指定要創建的Tab的類型它在屬性窗口上是否顯示由PropertyTabAttribute的PropertyTabScope參數來指定指定為Component范圍的屬性頁的可見性由有PropertyTabAttribute特性的組件的可見性來決定Document范圍的屬性頁則可以在當前項目的設計中都可見他的默認值是PropertyTabScopeComponent
  
  舉一個例子來說看看FunkyButton項目FunkyButton是一個擴展了PropertyTab的UserControl而且可以讓我們把控件定為不規則的多邊形
   
  圖 FunkyButton
  
  當前選擇的屬性頁就是屬性窗口從被選擇的控件的屬性中得到的屬性頁因此就允許來操縱顯示屬性的不同集合Events頁就是像屬性一樣以某種方式來處理事件在這個例子中屬性頁就創建了表示控件頂點的屬性
  
  NET framework中的屬性用PropertyDescriptor類來封裝PropertyDescriptor本身是一個抽象類framework中由他派生的類提供了訪問組件的開放屬性的方法不過屬性窗口是直接作用在PropertyDescriptor上而不是直接作用在屬性上因此我們就可以寫自己的PropertyDescriptor來做一些特殊的工作在這個例子裡我們就有一個屬性表示控件的頂點數另一個就表示每一個頂點再次注意一下我們在屬性窗口上增加頁並不相應的作用在其他對象上
  
  當屬性窗口向PropertyTab詢問Properties的時候它就調用GetProperties方法對於我們的示例程序這個方法就像下面的一樣
  
  public override PropertyDescriptorCollection
  
  GetProperties(ITypeDescriptorContext context object component
  
  Attribute[] attrs)
  
  {
  
  // our list of props
  
  //
  
  ArrayList propList = new ArrayList();
  
  // add the property for our count of vertices
  
  //
  
  propListAdd(new NumPointsPropertyDescriptor(this));
  
  // add a property descriptor for each vertex
  
  //
  
  for (inti = ; i < ((FunkyButton)component)PointsCount; i++)
  
  {
  
  propListAdd(new VertexPropertyDescriptor(thisi));
  
  }
  
  // return the collection of PropertyDescriptors
  
  PropertyDescriptor[] props =
  
  (PropertyDescriptor[])propListToArray(typeof(PropertyDescriptor));
  
  return new PropertyDescriptorCollection(props);
  
  }
  
  GetProperties僅僅是返回一些屬性描述的集合PropertyDescriptors是相當的簡單仔細查看這些代碼以了解他們是怎麼工作的
  
  FunkyButton同時示例了下拉列表編輯器的實現對於每一個點我們不是簡單的輸入坐標的X和Y值我們會圖示FunkyButton的形狀而且可以用圖形化的方法改變點的位置這樣設置的編輯樣式更加地友好
   
  圖 圖形化的點向量
  
  由於訂制的PropertyTab提供了屬性重載這個屬性的編輯器也是很容易的只要簡單地重載PropertyDescriptor的GetEditor方法然後返回訂制組件的實例就可以了
  
  public override object GetEditor(Type editorBaseType)
  
  {
  
  // make sure were looking for a UITypeEditor
  
  //
  
  if (editorBaseType == typeof(SystemDrawingDesignUITypeEditor))
  
  {
  
  // create and return one of our editors
  
  //
  
  if (editor == null)
  
  {
  
  editor = new PointUIEditor(ownertarget);
  
  }
  
  return editor;
  
  }
  
  return baseGetEditor(editorBaseType);
  
  }
  
  設計編輯器同樣簡單編輯器就是一個簡單的UserControl所以我們就可以像設計其他的windowsForms對象一樣來做
   
  圖 Designing the editor
  
  最後當用戶在屬性窗口中點擊下拉箭頭時我們的編輯器就可以將剛才創建UI編輯器彈出來了PointUIEditor中的UITypeEditorEditValue重載後就可以實現了
  
  public override object EditValue(
  
  ITypeDescriptorContext context
  
  IServiceProvider sp object value)
  
  {
  
  // get the editor service
  
  IWindowsFormsEditorService edSvc =
  
  (IWindowsFormsEditorService)spGetService(typeof(IWindowsFormsEditorService));
  
  // create our UI
  
  if (ui == null)
  
  {
  
  ui = new PointEditorControl();
  
  }
  
  // initialize the ui with the settings for this vertex
  
  uiSelectedPoint = (Point)value;
  
  uiEditorService = edSvc;
  
  uiTarget = (FunkyButton)contextInstance;
  
  // instruct the editor service to display the control as a
  
  // dropdown
  
  edSvcDropDownControl(ui);
  
  // return the updated value;
  
  return uiSelectedPoint;
  
  }
  
  我們同樣可以使用它
  
  在你自己的應用中可以擁有和IDE屬性窗一樣的特性把SystemWindowsFormsPropertyGrid的控件添加到IDE中的ToolBox中通過獲取在ToolBox的Component標簽裡的PropertyGrid
  
  PropertyGrid和其他的控件工作是一樣的你可以anchor或者是Dock他改變它的色彩等下面的列表列出了PropertyGrid的一些有趣的屬性
   
  這些屬性都可以在設計時設置在運行時可以操作PropertyGrid讓他顯示的你的對象下面是顯示一個button的例子在這個例子中PorpertyGrid的幫助和toolbox都被隱藏了就像上面提到的你可以設置他自己的屬性
  
  圖 隱藏了toolbar和幫助信息的PropertyGrid
  
  結論
  
  NET framework和Visual Studio NET給屬性窗口增加了相當多的功能由於屬性窗口是RAD的核心這些特性可以在保持易用性的同時有很多的擴展也因此在Visual Basic中用的很普遍就像可以在我們的程序中使用PropertyGrid我們可以把更多的時間放在如何寫好程序上從而簡化我們的UI工作
  
  下面的代碼是我實現的關於PointF的類型轉換如果是自定義類型構造方式完全一樣在重載時最關鍵的地方就是GetPropertys的實現不能直接返回基類的方法否則子屬性的值是修改不了的必須返回TypeDescriptor的GetPropertys至於為什麼請自行查閱MSDN上相關文章的介紹
  
  #region PointF的轉換類實現
   /// <summary>
   /// PointF的轉換類實現
   /// </summary>
   internal sealed class PointFConverter : TypeConverter
   {
  
   /// <summary>
   /// 重載TypeConverter的CanConvertFrom方法
   /// </summary>
   /// <param name=context></param>
   /// <param name=sourceType></param>
   /// 要測試的目標類型
   /// <returns></returns>
   public override bool CanConvertFrom(ITypeDescriptorContext context
  Type sourceType)
   {
  if (sourceType == typeof(string)) //sourceType的類型是Type
  {
  return true;
  }
  return baseCanConvertFrom(context sourceType);
   }
  
   /// <summary>
   /// 重載TypeConverter的ConvertFrom方法
   /// 定義從源類型到目標類型的轉換算法
   /// </summary>
   /// <param name=context></param>
   /// <param name=culture></param>
   /// 本地化參數
   /// <param name=value></param>
   /// 輸入字串
   /// <returns></returns>
   public override object ConvertFrom(ITypeDescriptorContext context CultureInfo culture object value)
   {
  if (value is string) //value是類型實例
  {
  string[] v = ((string)value)Split(new char[] {});
  return new PointF
From:http://tw.wingwit.com/Article/program/net/201311/12720.html
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.