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

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

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

  擴展屬性和字符串轉換TypeConverter和屬性窗口
  
  NET屬性窗口最重要的一個特性就是可以顯示嵌套的屬性這樣就提供了比屬性類別更加細化和更有邏輯的分類嵌套屬性對於類目顯示和排序顯示都是適用的這樣可以讓屬性列表更加緊湊比如我們用帶有子屬性X和Y的一個Location屬性來代替Top和Left兩個屬性就更加合理
   
  圖嵌套屬性
  
  不過如何來決定一個屬性可以展開呢?這些不是由屬性窗口來決定而是取決於屬性自己的類型NET framework中每一種類型都是和一個TypeConverter聯系在一起的比如Boolean和string的TypeConverter就不會允許展開因為讓boolean類型含有子屬性是沒有意義的
  
  在NET framework中TypeConverter實際上是執行了不少的方法在屬性窗口中就更多了正像他的名字所說明的那樣TypeConverter提供了一種動態的從一種類型改變到另一種類型的標准方式事實上屬性窗口只和string打交道所以他就依賴於TypeConverter來進行類型之間的轉換(主要是和string類型的轉換)TypeConverter同樣是可以提供擴展性能以及復雜類型來和屬性窗口交互
  
  比如看下面這個Person類
  
  [TypeConverter(typeof(PersonConverter))]
  
  public class Person
  
  {
  
  private string firstName = ;
  
  private string lastName = ;
  
  private intage = ;
  
  
  
  public int Age
  
  {
  
  get
  
  {
  
  return age;
  
  }
  
  set
  
  {
  
  age = value;
  
  }
  
  }
  public string FirstName
  
  {
  
  get
  
  {
  
  return firstName;
  
  }
  
  set
  
  {
  
  thisfirstName = value;
  
  }
  
  }
  
  public string LastName
  
  {
  
  get
  
  {
  
  return lastName;
  
  }
  
  set
  
  {
  
  thislastName = value;
  
  }
  
  }
  
  }
  
  我們注意到Person類被指定了TypeConverterAttribute特性TypeConverterAttribute特性還指定了這個類的類型轉換器(PersonConverter)如果沒有指定TypeConverterAttribute特性默認使用TypeConverter類對於一些簡單數據類型比如Font Point等TypeConverter可以很好地工作但如果數據類型比較復雜那麼它對類型是轉換可能就不是我們希望的那樣因此我們有必要從TypeConverter派生自己的類型轉換器在這裡就是PersonConverter本例中我們首先重載了GetPropertiesSupported和GetProperties方法來決定屬性是否可以展開
  
  internal class PersonConverter : TypeConverter
  
  {
  
  public override PropertyDescriptorCollection
  
  GetProperties(ITypeDescriptorContext context
  
  object value
  
  Attribute[] filter)
  
  {
  
  return TypeDescriptorGetProperties(value filter);
  
  }
  
  public override bool GetPropertiesSupported(
  
  ITypeDescriptorContext context)
  
  {
  
  return true;
  
  }
  
  }
  
  在通常情況下直接使用TpyeConverter進行轉換已經足夠了簡單的擴展就是從TypeConverter直接派生你所要的類型轉換器更復雜的擴展就需要從ExpandableObjectConverter派生類型轉換器了現在我們修改PersonConverter來轉換一個Person類並且顯示一個字符串
  
  internal class PersonConverter : ExpandableObjectConverter
  
  {
  
  public override bool CanConvertFrom(
  
  ITypeDescriptorContext context Type t)
  
  {
  
  if (t == typeof(string))
  
  {
  
  return true;
  
  }
  
  return baseCanConvertFrom(context t);
  
  }
  
  public override object ConvertFrom(
  
  ITypeDescriptorContext context
  
  CultureInfo info
  
  object value)
  
  {
  
  if (value is string)
  
  {
  
  try
  
  {
  
  string s = (string) value;
  
  // parse the format Last First (Age)
  
  //
  
  int comma = sIndexOf();
  
  if (comma != )
  
  {
  
  // now that we have the comma get
  
  // the last name
  
  string last = sSubstring( comma);
  
  int paren = sLastIndexOf(();
  
  if (paren != && sLastIndexOf()) == sLength )
  
  {
  
  // pick up the first name
  
  string first = sSubstring(comma + paren comma );
  
  // get the age
  
  int age = IntParse(
  
  sSubstring(paren +
  
  sLength paren ));
  
  Person p = new Person();
  
  pAge = age;
  
  pLastName = lastTrim();
  
  pFirstName = firstTrim();
  
  return p;
  
  }
  
  }
  
  }
  
  catch {}
  
  // if we got this far complain that we
  
  // couldnt parse the string
  
  //
  
  throw new ArgumentException(
  
  Can not convert + (string)value +
  
   to type Person);
  
  }
  
  return baseConvertFrom(context info value);
  
  }
  
  public override object ConvertTo(
  
  ITypeDescriptorContext context
  
  CultureInfo culture
  
  object value
  
  Type destType)
  
  {
  
  if (destType == typeof(string) && value is Person)
  
  {
  
  Person p = (Person)value;
  
  // simply build the string as Last First (Age)
  
  return pLastName + +
  
  pFirstName +  ( + pAgeToString() + );
  
  }
  
  return baseConvertTo(context culture value destType);
  
  }
  
  }
  
  現在看看我們的Person屬性在指定了PersonConverter類型轉換器之後既可以展開又可以通過兩種方式來操作了直接修改和使用子屬性
  
  圖 實現展開的TypeConverter
  
  要使用上面的代碼我們就生成一個UserControl並且寫下如下的代碼
  
  private Person p = new Person();
  
  public Person Person
  
  {
  
  get
  
  {
  
  return p;
  
  }
  
  set
  
  {
  
  thisp = value;
  
  }
  
  }
From:http://tw.wingwit.com/Article/program/net/201311/12805.html
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.