haoxiaobo

从C到C++又到.net, 有一些心得, 和大家交流下...
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

定义属性在设计器中的编辑方式

Posted on 2005-06-02 17:17  HAL9000  阅读(2392)  评论(3编辑  收藏  举报
问题一: 自已写到一个类, 其中有一个属性是字串型, 是用来保存一个文件名的,  这个类需要客户在使用时能在PropertyGrid里runtime修改内容, 友好的方式当然是让客户在PropertyGrid里可以有一个"..."的按钮, 点一下之后打开一个openfiledialog, 选择一个文件之后返回, 文件的全路径就放在属性值的框里了. 如何达到这个目的?

比如这个类如下:
public class class1
{
    
public class1()
    
{    
    }

    
    
// 

    
private string _s;
    
public string s
    
{
        
get{return this._s;}
        
set{this._s = value;}
    }

}


这样的话在PropertyGrid里s属性的后面只有一个简简单单的编辑框, 为了使s的编辑区可以出现一个"..." 按钮, 并且可以用文件打开对话框选择文件, 可以使用EditorAttribute属性对这个属性进行标记:

[Editor(
typeof(System.Windows.Forms.Design.FileNameEditor), 
        
typeof(System.Drawing.Design.UITypeEditor))]
public string S
{
    
get{return this._s;}
    
set{this._s = value;}
}

FileNameEditor类提供了一个打开文件的对话框, 以编辑属性值, 这个类派生于UITypeEditor类, UITypeEditor是所有设计时界面的基类.

这样就可以达到有文件对话框的目的了, 但是如果想要指定只选择某一种文件类型, 如"WAV"文件, 那就得派生FileNameEditor, 重写有关的方法.

public class SoundFileEditor:System.Windows.Forms.Design.FileNameEditor
{
    
protected override void InitializeDialog(OpenFileDialog openFileDialog)
    {
        
base.InitializeDialog (openFileDialog);
        
// 在基类初始代完对话框之后, 可以对这个对话框做一些手脚.
        openFileDialog.Filter = "wav and vox file(*.wav, *.vox)|*.wav;*.vox|wav files (*.wav)|*.wav|vox files (*.vox)|*.vox|All files (*.*)|*.*";
    }
}

再把Class1中的S的EditorAttribute改为派生的这个子类, 现在对话框里的文件过滤器改为你想要的了.

你甚至可以从UITypeEditor自己重新派生一个子类出来, 自己写一个能弹出"保存文件"对话框的UI编辑类. 注意在重写UITypeEditor的
public virtual new System.Object EditValue ( System.ComponentModel.ITypeDescriptorContext context , System.IServiceProvider provider , System.Object value )
方法, 注意返回自己需要对象就可以了.

问题二:  如何设定一个类的"默认值编辑器"?
例如: 比如有一个类叫SoundFileName专门用来处理声音文件名, 如果Class1中有一个属性FileName是SoundFileName类型, 这个属性在PropertyGrid里编辑器里默认情况下是没有办法编辑的, 为了让SoundFileName类可以在propertyGrid里可以编辑, 必须对SoundFileName进行属性标志, 指定一个默认的编辑器. 假定我们还是希望通过"打开文件"对话框来指定一个文件的方式生成一个SoundFileName对象, 那么我们可以写一个从UITypeEditor中直接或间接派生的子类, 以完成编辑对象内容的操作.

如下代码所示, 这个专门编辑SoundFileName对象的类叫SoundfileNameEditor, 我们随后实现它, 现在先看SoundFileName的实现. 注意class之前的标记:

[EditorAttribute(typeof(SoundFileNameEitor), 
        
typeof (System.Drawing.Design.UITypeEditor))] 
public class SoundFileName
{
    
private string _filename;    
    
public string FileName
    {
        
get{return _filename;}
    }

    
public SoundFileName(string s)
    {
        
this._filename = s;
    }
}

这里定义了此类的值编辑器为SoundFileNameEditor类, 这个类我们需要从UITypeEditor或是其子类中派生出来, 重写其EditValue方法, 以可以返回一个SoundFileName对象.

为了省事, 我就不再从UITypeEditor派生了, 而是从SoundFileEditor派生, SoundFileEditor已经把文件名过滤器修改了, 但是SoundFileEditor的EditValue返回的是一个字串, 这次只要修改SoundFileEditor的EditValue的值就可以了.

public class SoundFileNameEditor: SoundFileEditor
{
    
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
    {
        SoundFileName sfn 
= value as SoundFileName;
        
        
return new SoundFileName(base.EditValue (context, provider, sfn==null?"":sfn.FileName) as string);
    }
}

注意, 这个EditValue总是会返回一个新的对象, 把从前的对象扔掉, 你可以通过判断value是不是null来决定是否新建一个对象, 还是只是修正一下其中的文件名, 这里不再多说了.

现在你在PropertyGrid里可以编辑SoundFileNmae对象了, 编辑器弹出一个打开文件对话框, 选择了文件之后, 根据文件名建立了一个SoundFileName对象.

最后提示一下, 不知道你注意到了没有, 当选择了文件名建立了一个SoundFileName对象之后, 在编辑框里的内容是"testanything.SoundFileName", 用户看起来不会太高兴, 也不直观, 这个也好办, 你可以重写SoundFileName的ToString()方法来用任何方式显示你想要内容.