为SSIS编写自定义数据流组件之进阶篇:自定义属性的下拉式编辑器
之前的一篇文章中,我们讲解到了,如果一个自定义属性是可选值,我们可能更希望用下拉列表的方式让用户选择,而不是弹出一个对话框。
http://www.cnblogs.com/chenxizhang/archive/2009/06/21/1507686.html
上面这一篇讲解的是如何通过枚举类型的方式实现简单的下拉列表。很显然的一个问题是,枚举的个数是固定的,而且是有限的。
那么有没有办法让我们的列表更加灵活呢?例如动态生成一个列表。答案是:可以的。这就是本篇文章探讨的问题
我们首先来看一下具体的效果
还是我们那个“文件夹数据源”的组件,它的Folder属性,现在点击下拉框之后,能够自动地枚举出来C盘下面的所有子目录,以供选择。这当然会更加好一些。
下面来看看我们是怎么实现的
1. 创建一个单独的UITypeEditor
public class MyTypeUIDropDownEditor : System.Drawing.Design.UITypeEditor {
IWindowsFormsEditorService editorService = null;
public override object EditValue(System.ComponentModel.ITypeDescriptorContext context,
IServiceProvider provider, object value)
{
if (context != null && context.Instance != null && provider != null)
{
editorService = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
if (editorService != null)
{
string current = "没有选择文件夹";
if (value != null)//这个value其实就是当前用户已经选择好的值
current = value.ToString();
MyTypeUIDropDownControl ctrl = new MyTypeUIDropDownControl(current);
ctrl.ValueChanged += new MyTypeUIDropDownControl.ValueChangedHander(ctrl_ValueChanged);
//添加这个事件的目的是在值发生变化的时候,自动把列表关闭掉
//这是一个自定义事件
editorService.DropDownControl(ctrl);
value = ctrl.Folder;
return value;
}
}
return value;
}
void ctrl_ValueChanged()
{
editorService.CloseDropDown();
}
public override UITypeEditorEditStyle GetEditStyle(
System.ComponentModel.ITypeDescriptorContext context)
{
return UITypeEditorEditStyle.DropDown;
}
public override bool IsDropDownResizable
{
get
{
return true;
}
}
}
2. 我们在这个编辑器中,需要用到一个用户控件。直接继承UserControl
这个控件上,有一个ListBox,它的Dock属性设置为Fill
控件的代码大致如下
using System;
using System.Windows.Forms;
using System.IO;
namespace MyDataFlowComponentSample
{
public partial class MyTypeUIDropDownControl : UserControl
{
public MyTypeUIDropDownControl()
{
InitializeComponent();
foreach (var item in Directory.GetDirectories("c:\\"))
{
lstFolder.Items.Add(item);
}
}
public MyTypeUIDropDownControl(string current)
: this()
{
lstFolder.SelectedValue = current;
}
private string folder;
public string Folder
{
get { return folder; }
set { folder = value; }
}
private void lstFile_SelectedIndexChanged(object sender, EventArgs e)
{
folder = lstFolder.SelectedItem.ToString();
if (ValueChanged != null)
ValueChanged();
}
public delegate void ValueChangedHander();
public event ValueChangedHander ValueChanged;
}
}
3. 将我们的Editor与自定义属性进行关联
folder.UITypeEditor = typeof(MyTypeUIDropDownEditor).AssemblyQualifiedName;
4. 生成项目,部署,测试。
如果不出意外,你就可以看到本文开篇出的那个效果
5. 更多联想。只要你愿意,你当然可以在那个UserControl中做更多的事情,让你的编辑器下拉列表更加酷。看看下面这样的效果
using System; using System.Windows.Forms; using System.IO; using System.Drawing; namespace MyDataFlowComponentSample { public partial class DropDownControl : UserControl { public DropDownControl() { InitializeComponent(); } protected override void OnLoad(EventArgs e) { int i = 0; Random rnd = new Random(); foreach (var item in Directory.GetDirectories("c:\\")) { Button bt = new Button(); bt.Width = this.Width - 40; bt.Height = 40; bt.BackColor = Color.FromArgb(rnd.Next(255), rnd.Next(255), rnd.Next(255));//随机给一个颜色 bt.Text = item; bt.Left = 0; bt.Top = i * 40; i++; bt.Click += new EventHandler(bt_Click); panel1.Controls.Add(bt); } } private string folder; public string Folder { get { return folder; } set { folder = value; } } void bt_Click(object sender, EventArgs e) { folder = ((Button)sender).Text; } } }
如你所见,我动态创建了一批按钮,并且他们的背景色是随机产生的,这就增加了一些趣味性,不是吗
到这里为止,我们针对数据源组件的开发全部介绍完了。下一篇开始将介绍到转换组件和目标组件。但是对于它们与数据源组件相似的地方,例如自定义属性和自定义编辑器,我们都不会重复介绍了。