Visual Studio 设计时属性 - 表单列表下拉菜单

发布于 2024-08-30 20:16:23 字数 332 浏览 8 评论 0原文

[编辑] 需要明确的是,我知道如何通过反射获取表单列表。我更关心设计时属性网格。

我有一个具有 Form 类型公共属性的用户控件。
我希望能够在设计时从下拉列表中选择表单。
我想从一组命名空间填充表单下拉列表:UI.Foo.Forms

如果您有 Control 的公共属性,这将像这样工作。在设计时,该属性将自动填充表单上所有控件的下拉列表,供您选择。我只想用命名空间中的所有表单填充它。

我该怎么做呢?我希望我说得足够清楚,这样就不会造成混乱。如果可能的话,我正在寻找一些代码示例。当我还有其他截止日期要满足时,我会尽量避免在这方面花费太多时间。

提前感谢您的帮助。

[EDIT] To be clear, I know how to get a list of forms via reflection. I'm more concerned with the design time property grid.

I have a user control with a public property of the type Form.

I want to be able to select a form at design time from a dropdown.

I want to populate the form dropdown list from a set namespace: UI.Foo.Forms

This would work like if you have a public property of Control. At design time, the property will automatically populate a dropdown with all the controls on the form, for you to select from. I just want to populate it with all the forms in a namespace.

How do I go about doing this? I hope I'm being clear enough so there is no confusion. I'm looking for some code examples if at all possible. I'm trying to avoid having to spend too much time on this when I have other deadlines to meet.

Thanks for your help in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

小…楫夜泊 2024-09-06 20:16:23

您可以通过反射轻松获取类:

var formNames = this.GetType().Assembly.GetTypes().Where(x => x.Namespace == "UI.Foo.Forms").Select(x => x.Name);

假设您从与表单相同的程序集中的代码调用此类,您将获得“UI.Foo.Forms”命名空间中的所有类型的名称。然后,您可以在下拉列表中呈现此内容,并最终再次实例化用户通过反射选择的任何一个:

Activator.CreateInstance(this.GetType("UI.Form.Forms.FormClassName"));

[编辑] 为设计时内容添加代码:

[Browsable(true)]
[Editor(typeof(TestDesignProperty), typeof(UITypeEditor))]
[DefaultValue(null)]
public Type FormType { get; set; }

在您的控件上,您可以创建一个 Form 属性,如下所示 必须定义的编辑器类型。该代码非常不言自明,只需进行最少的调整,您就可以让它准确地生成您想要的内容。

public class TestDesignProperty : UITypeEditor
{
    public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
    {
        return UITypeEditorEditStyle.DropDown;
    }

    public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
    {
        var edSvc = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));

        ListBox lb = new ListBox();
        foreach(var type in this.GetType().Assembly.GetTypes())
        {
            lb.Items.Add(type);
        }

        if (value != null)
        {
            lb.SelectedItem = value;
        }

        edSvc.DropDownControl(lb);

        value = (Type)lb.SelectedItem;

        return value;
    }
}

You can easily get the classes via Reflection:

var formNames = this.GetType().Assembly.GetTypes().Where(x => x.Namespace == "UI.Foo.Forms").Select(x => x.Name);

Assuming you're calling this from code in the same assembly as your forms, you'll get the names of all the types that are in the "UI.Foo.Forms" namespace. You can then present this in the dropdown and, eventually, instantiate whichever is selected by the user via reflection once more:

Activator.CreateInstance(this.GetType("UI.Form.Forms.FormClassName"));

[Edit] Adding code for the design time stuff:

On your control you can create a Form property as such:

[Browsable(true)]
[Editor(typeof(TestDesignProperty), typeof(UITypeEditor))]
[DefaultValue(null)]
public Type FormType { get; set; }

Which references the Editor type that must be defined. The code is pretty self-explanatory, with a minimal amount of tweaking, you'll likely be able to get it to produce exactly what you want.

public class TestDesignProperty : UITypeEditor
{
    public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
    {
        return UITypeEditorEditStyle.DropDown;
    }

    public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
    {
        var edSvc = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));

        ListBox lb = new ListBox();
        foreach(var type in this.GetType().Assembly.GetTypes())
        {
            lb.Items.Add(type);
        }

        if (value != null)
        {
            lb.SelectedItem = value;
        }

        edSvc.DropDownControl(lb);

        value = (Type)lb.SelectedItem;

        return value;
    }
}
等风来 2024-09-06 20:16:23

通过单击选择项目时,下拉列表不会关闭,因此这可能很有用:

为列表框分配单击事件处理程序并添加事件处理程序函数

public class TestDesignProperty : UITypeEditor
{

    // ...

    IWindowsFormsEditorService editorService;

    public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
        {
            // ...
            editorService = edSvc ; // so can be referenced in the click event handler

            ListBox lb = new ListBox();
            lb.Click += new EventHandler(lb_Click);
            // ... 
        }



    void lb_Click(object sender, EventArgs e)
    {
        editorService.CloseDropDown();
    }

}

The dropdown does not close when item gets selected by clicking it, so this could be useful:

assign the click event handler for the listbox and add the event handler function

public class TestDesignProperty : UITypeEditor
{

    // ...

    IWindowsFormsEditorService editorService;

    public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
        {
            // ...
            editorService = edSvc ; // so can be referenced in the click event handler

            ListBox lb = new ListBox();
            lb.Click += new EventHandler(lb_Click);
            // ... 
        }



    void lb_Click(object sender, EventArgs e)
    {
        editorService.CloseDropDown();
    }

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文