编写windows 控件需要注意的几个标签属性(Attribute)
我們在編程控件(Control)或者是組件(Component)的時候總是要暴露一些屬性(Property,不同于Attribute)給用戶進行配置,以得到可以變化的功能。
mapserver .NET組件編程(1) 基礎 中說到的
1、Component在Run Time時不能呈現UI,而Control可以在Run Time時呈現UI(但是vs 2005里的asp.net中的SqlDataSource是Control,但是它不能呈現UI)。2、Component是貼在容器Container上的,而Control則是貼在Windows Form或者Web Form上的。 舉例來說,SqlCommand是個Component,DataGrid則是一個Control。
mapserver寫了.net 組件編程系列,值得看看。
就說,如何在設計時對某個屬性(property)提供一些幫助,那么就需要用到幾個重要的屬性(Attribute)。
?
TypeConverter, Editor 標簽屬性下面ImageIndex的屬性被貼上標簽屬性。
1: [//TypeConverter(typeof(ImageIndexConverter)), 2: Editor(typeof(newimageEditoer), typeof(UITypeEditor)), 3: Description("")] 4: public int ImageIndex 5: { 6: get { return myVar; } 7: set { myVar = value; } 8: }TypeConverter 指類型轉換。
Editor 在設計時,調用哪個Editor對它進行編輯修改。
DesignerSerializationVisibilityAttribute:指定通過Property Editor得到的結果是否保存在代碼中。
LocalizableAttribute:用戶要本地化某個窗體時,任何具有該特性的屬性都將自動永久駐留到資源文件中。
?
*注意TypeConverter 和 Editor有時候是相互作用的。比如上面的例子,大家可以用reflector看看微軟的buttonBase 里面的ImageIndex的標簽屬性是什么,并找到ImageIndexConverter 和對應的Editor [ImageIndexEditor]。 如果我們繼續是用TypeConverter[ImageIndexConverter ],重新完成一個新的Editor[newimageEditoer],你會發現新的Editor是不起作用的。
?
接下來,我們看看Serializable標簽屬性會在VS自動代碼起到什么樣的作用,接著,我們再回過頭看看ButtonBase里面ImageIndex屬性怎么通過在標簽屬性TypeConverter 和Editor配合下,我們就能在設計的時候選擇button對應的圖片的?
?
Serializable 標簽屬性 1: [Serializable] 2: public class XButton 3: {注意,如果貼上Serilizable,則代碼會自動生成(來之與from1.designer.cs文件的片段) 1: this.userControl11.xButtons.Add(((WindowsControlLibrary1.XButton)(resources.GetObject("userControl11.xButtons"))));也就說它是通過從資源文件來保存(序列)值。如果不貼上[Serializable]標簽,則自動生成在代碼里面(來之與from1.designer.cs文件的片段) 1: //先實例 2: WindowsControlLibrary1.XButton xButton1 = new WindowsControlLibrary1.XButton(); 3: WindowsControlLibrary1.XButton xButton2 = new WindowsControlLibrary1.XButton(); 4: // 5: xButton1.component = null; 6: xButton1.ImageIndex = -1; 7: xButton2.component = null; 8: xButton2.ImageIndex = -1; 9: this.userControl11.xButtons.Add(xButton1); 10: this.userControl11.xButtons.Add(xButton2);?
描述一下xButton類, xButtons是一個List<xButton>集合類型。
1: public class XButton 2:? 3:? 4: public XButton() 5: { 6: 7: } 8:? 9: private string _txt = ""; 10: [DefaultValue("")] 11: public string Text 12: { 13: get { return _txt; } 14: set { _txt = value; } 15: } 16:? 17: private int myVar = -1; 18:? 19: [//TypeConverter(typeof(ImageIndexConverter)), 20: r(typeof(newimageEditoer), typeof(UITypeEditor)), 21: iption("")] 22: public int ImageIndex 23: { 24: get { return myVar; } 25: set { myVar = value; } 26: } 27:? 28: [NonSerialized] 29: private System.ComponentModel.Component _im; 30: [Browsable(false)] 31: public System.ComponentModel.Component component 32: { 33: get { return _im; } 34: set { _im = value; } 35: } 36:? 37:?
ButtonBase里面ImageIndex屬性怎么通過在標簽屬性TypeConverter 和Editor配合下,我們就能在設計的時候選擇button對應的圖片的?先看看UI,一開始,我以為Editor是完成了所有編輯功能(編輯樣式[EditStyle]你可以選擇三種,一種none,一種是下拉框,一種是對話框形式)
這個可以在繼承UITypeEditor類復寫
1: public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) 2: { 3:? 4: return UITypeEditorEditStyle.Modal; 5: //return base.GetEditStyle(context); 6: }?
那么,我們是如何看到下拉框圖片的呢?本來我以為這部分會在Editor里面實現,實際上不是的。有部分是在ImageIndexConverter中,它創建了Image的Collection
1: public override TypeConverter.StandardValuesCollection GetStandardValues(ITypeDescriptorContext context) 2: { 3: if ((context != null) && (context.Instance != null)) 4: { 5: object instance = context.Instance; 6: PropertyDescriptor imageListProperty = ImageListUtils2.GetImageListProperty(context.PropertyDescriptor, ref instance); 7: while ((instance != null) && (imageListProperty == null)) 8: { 9: PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(instance); 10: foreach (PropertyDescriptor descriptor2 in properties) 11: { 12: if (typeof(ImageList).IsAssignableFrom(descriptor2.PropertyType)) 13: { 14: imageListProperty = descriptor2; 15: break; 16: } 17: } 18: if (imageListProperty == null) 19: { 20: PropertyDescriptor descriptor3 = properties[this.ParentImageListProperty]; 21: if (descriptor3 != null) 22: { 23: instance = descriptor3.GetValue(instance); 24: continue; 25: } 26: instance = null; 27: } 28: } 29: if (imageListProperty != null) 30: { 31: ImageList list = (ImageList)imageListProperty.GetValue(instance); 32: if (list != null) 33: { 34: object[] objArray; 35: int count = list.Images.Count; 36: if (this.IncludeNoneAsStandardValue) 37: { 38: objArray = new object[count + 1]; 39: objArray[count] = -1; 40: } 41: else 42: { 43: objArray = new object[count]; 44: } 45: for (int i = 0; i < count; i++) 46: { 47: objArray[i] = i; 48: } 49: return new TypeConverter.StandardValuesCollection(objArray); 50: } 51: } 52: } 53: if (this.IncludeNoneAsStandardValue) 54: { 55: return new TypeConverter.StandardValuesCollection(new object[] { -1 }); 56: } 57: return new TypeConverter.StandardValuesCollection(new object[0]); 58: }里面的實際上用了反射的機制來獲取一個ImageList并把其中的Image加入到一個TypeConverter.StandardValuesCollection,但具體是誰來控制把這集合顯示出來的呢?我不知道。
至于把它顯示出來是在Editor里面實現的,其中調用了方法GetImage,就是去找到Image并畫出來。
1: public override void PaintValue(PaintValueEventArgs e) 2: { 3: if (this.ImageEditor != null) 4: { 5: Image image = null; 6: if (e.Value is int) 7: { 8: image = this.GetImage(e.Context, (int)e.Value, null, true); 9: } 10: else if (e.Value is string) 11: { 12: image = this.GetImage(e.Context, -1, (string)e.Value, false); 13: } 14: if (image != null) 15: { 16: this.ImageEditor.PaintValue(new PaintValueEventArgs(e.Context, image, e.Graphics, e.Bounds)); 17: } 18: } 19: }?
關于這方面的一些資料
編寫與.NET屬性窗口交互的RAD組件
其中有一段話,我很感興趣
在實現數據綁定的組件中,清除掉DataSource的值,自然的就會清除掉DataMember的值。RefreshPropertiesAttribute就讓我們實現這個功能。他的默認值是“none,”不過如果指定其他的特性,屬性窗口就可以在改變這個屬性值的同時,自動的更新被更新屬性的值。另外的兩個值是Repaint,它讓屬性窗口重新獲取屬性的值并且重畫他們,還有就是All,它就意味著組件自己要重新獲取屬性的值。如果值的改變導致屬性的數目的增減,那么我們就要使用All。不過要注意到這個一般用在高級場合,并且速度要比Repaint慢。RefreshProperties.Repaint適用于大部分的情況。所謂的刷新調用的是什么方法來進行? 比如,我設置了某個屬性的值,這個屬性的值又是關于空間外觀的,那么如何來觸發這個事件?
轉載于:https://www.cnblogs.com/king_astar/archive/2008/05/05/1183678.html
總結
以上是生活随笔為你收集整理的编写windows 控件需要注意的几个标签属性(Attribute)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于迷笛音乐节的重大通知-_-
- 下一篇: 实战小技巧系列(4):WinForm简单