2

作为我第一次尝试创建自定义控件,我正在扩展 Gridview Web 控件。

作为扩展的一部分,我将网格列标题的本地化封装在控件中。除其他外,我公开了几个属性来启用此功能:

bool AutoLocalizeColumnHeaders - 启用该功能

string HeaderResourceFile - 标识一个强类型资源类,从中获取标题文本

我正在重写 OnRowDataBound 处理程序并使用反射获取适当的 ResourceManager 来填充标题文本。这一切都很好,但我想在属性窗口中显示可用的强类型资源类列表供用户选择,而不是他们必须手动输入名称。

我创建了一个 TypeConverter 来显示一个下拉列表,在该下拉列表中显示可用的类,但不知道如何获取要显示的可用类名列表?

我已经尝试了很长一段时间没有成功,并且正处于失去理智的地步。我假设必须有某种方法可以使用反射来实现这一点?

4

3 回答 3

1

我想我现在已经找到了解决方案。

从 Page_Load 事件中运行以下内容给了我 Resource 类名称:

String[] resourceClassNames = (from type in assembly.GetTypes()
   where type.IsClass && type.Namespace.Equals("Resources")
   select type.Name).ToArray();

所以我想我可以从 TypeConverter 的 GetResourceFileNames(ITypeDescriptorContext context) 函数内部做类似的事情,使用 context 参数来获取正确的程序集。不幸的是,我似乎只能获得自定义控件的程序集或 System.Web 程序集。

因此,我创建了一个 UITypeEditor,它有一个 IServiceProvider 传递到 EditValue 例程中。由此我能够创建一个 ITypeDiscoveryService 实例,然后我用它从正确的程序集中获取所有类型:

public override object EditValue(ITypeDescriptorContext context, 
                                 IServiceProvider provider, object value)
{
    // Check if all the expected parameters are here
    if (context == null || context.Instance == null || provider == null)
    {
        // returning with the received value
        return base.EditValue(context, provider, value);
    }

    // Create the Discovery Service which will find all of the available classes
    ITypeDiscoveryService discoveryService = (ITypeDiscoveryService)provider.GetService(typeof(ITypeDiscoveryService));
    // This service will handle the DropDown functionality in the Property Grid
    _wfes = provider.GetService(typeof(IWindowsFormsEditorService)) as IWindowsFormsEditorService;

    // Create the DropDown control for displaying in the Properties Grid
    System.Windows.Forms.ListBox selectionControl = new System.Windows.Forms.ListBox();
    // Attach an eventhandler to close the list after an item has been selected
    selectionControl.SelectedIndexChanged += new EventHandler(selectionControl_SelectedIndexChanged);
    // Get all of the available types
    ICollection colTypes = discoveryService.GetTypes(typeof(object), true);
    // Enumerate the types and add the strongly typed
    // resource class names to the selectionControl
    foreach (Type t in colTypes)
    {
        if (t.IsClass && t.Namespace.Equals("Resources"))
        {
            selectionControl.Items.Add(t.Name);
        }
    }
    if (selectionControl.Items.Count == 0)
    {
        selectionControl.Items.Add("No Resources found");
    }
    // Display the UI editor combo
    _wfes.DropDownControl(selectionControl);

    // Return the new property value from the UI editor combo
    if (selectionControl.SelectedItem != null)
    {
        return selectionControl.SelectedItem.ToString();
    }
    else
    {
        return base.EditValue(context, provider, value);
    }
}

void selectionControl_SelectedIndexChanged(object sender, EventArgs e)
{
    _wfes.CloseDropDown();
}

这似乎运作良好,尽管我希望有一种更时尚的方式来获取使用 LinQ 所需的类型,但我才刚刚开始研究 LinQ,并且在查询集合而不是查询时似乎无法获得正确的语法与前面的示例一样的数组。

如果有人可以建议可以做到这一点的 LinQ 语法,或者确实是完成整个事情的更好方法,那么它将是最受欢迎的。

于 2008-12-05T19:41:30.087 回答
0

在我之前发布的解决方案中,我想找到一种使用 LinQ 执行以下操作的方法:

    // Get all of the available types
    System.Collections.ICollection colTypes = discoveryService.GetTypes(typeof(object), true);
    // Enumerate the types and add the strongly typed resource class names to the selectionControl
    foreach (Type t in colTypes)
    {
        if (t.IsClass && t.Namespace.Equals("Resources"))
        {
            selectionControl.Items.Add(t.Name);
        }
    }

这似乎做生意:

    // Get all of the available class names from the Resources namespace
    var resourceClassNames = from Type t in discoveryService.GetTypes(typeof(object), true)
                        where t.IsClass && t.Namespace.Equals("Resources")
                        select t.Name;

    selectionControl.Items.AddRange(resourceClassNames.ToArray());

它看起来确实干净多了,我猜它的性能会更好,因为它没有循环遍历所有可用的类型,检查符合我的代码标准的类型;虽然我认为 LinQ 会为我做这件事,尽管是以更有效的方式?

于 2008-12-07T14:56:54.637 回答
0

有趣的想法。我想您的属性当前设置为字符串?我想知道您是否将您的属性设置为枚举,然后使用强类型资源类创建一个枚举,它是否足够聪明以在属性窗口中显示它们。它足够聪明,可以在后面的代码中显示它,看不出为什么它无法在属性窗口中加载它。

于 2008-12-05T18:25:31.597 回答