Visual Studio“选择资源"对话框替换 [英] Visual Studio "Select Resource" dialog replacement

查看:161
本文介绍了Visual Studio“选择资源"对话框替换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的项目中,我有超过750张图像资源.使用内置在选择资源"对话框中的VS是为winforms设计器中的按钮查找和选择一个图像的噩梦,比如说.

In my project I have more than 750 images in resource. Using VS built in "Select Resource" dialog is a nightmare to find and select one image - let's say - for a button in winforms designer.

如果它是像对话框这样的资源管理器,并且缺少搜索功能,它将更加有用.

It would be much more usable if it was some explorer like dialog and it is lack of search functionality.

  • 您是否知道如何替换此对话框?

  • Do you have any idea how to replace this dialog?

是否有任何扩展程序可以做到这一点?

Is there any extension that can do that?

如果没有这样的扩展名,我将创建一个扩展名/加载项.如果可以做到,您有任何实际经验吗?

If there is no such extension I would create an extension/add-in whatever I need to do. Do you have any real experience if it can be done at all?

我以为我会找到合适的dll并扩展其性能,但不幸的是,我找不到哪个dll包含此悲剧

I thought I will find the appropriate dll and extend its beaviour, but unfortunately I cannot find which dll contains this tragedy

任何帮助将不胜感激,谢谢!

Any help would be appreciated, thank you!

推荐答案

资源选择对话框是UITypeEditor.内部类ResourceEditorSwitch<T>是内部使用内部类ResourcePickerDialog的内部类,它们都在Visual Studio的程序集之一的Microsoft.VisualStudio.Windows.Forms.dll程序集中.

The Resource Select dialog is a UITypeEditor. It is the internal class ResourceEditorSwitch<T> which internally uses the internal class ResourcePickerDialog and both of them are in Microsoft.VisualStudio.Windows.Forms.dll assembly which is one of Visual Studio's assemblies.

由于该类的实现与Visual Studio程序集的其他一些内部类紧密相关,因此很难提取该类源代码并对其进行自定义,但是掌握这些类的相关信息将有助于我们了解一下它的源代码,让我们获得有关该类的更多信息.

Since the implementation of the class is tightly coupled with some other internal classes of Visual Studio's assemblies, so it's hard to extract the class source code and customize it, but you having those information about the class will help us to take a look at its source code and let us to have more information about the class.

自定义 Resource Select 对话框相反,您可以在设计时获取该类的实例,并且在显示对话框之前,使用代码操纵该对话框以具有类似gif,请注意我添加到对话框中的TextBox:

To customize the Resource Select dialogInstead you can get an instance of the class at design time, and before showing the dialog, manipulate the dialog using code to have a filtering feature like following gif, pay attention to the TextBox that I've added to the dialog:

您可以通过键入TextBox并使用键来过滤ListBox,而无需从TextBox更改焦点,您可以选择过滤的结果

You can filter the ListBox by typing in TextBox and using and keys, without changing the focus from TextBox you can select filtered results.

为此,您应该:

  1. 创建一个ControlDesigner并将其注册为控件的设计者.然后在其OnCreateHandle中找到要编辑的属性.例如BackgroundImage.
  2. 找到该属性的UITypeEditor.编辑器的类型为ResourceEditorSwitch<T>,它使用ResourcePickerDialog的实例.获取ResourcePickerDialog的实例.
  3. 获取resourcePickerUI字段并创建ResourcePickerUI对话框的实例.这是您应该更改的对话框.该对话框包含一些TableLayoutPanel.您应该在适当的位置插入TextBox并处理其TextChanged事件,并过滤ListBox中显示的值.所有控件都有名称,您可以简单地访问它们并更改其属性和值.

  1. Create a ControlDesigner and register it as designer of your control. Then in its OnCreateHandle find the property which you are going to edit. For example BackgroundImage.
  2. Find the UITypeEditor of that property. The editor is of type of ResourceEditorSwitch<T> which uses an instance of ResourcePickerDialog. Get the instance for ResourcePickerDialog.
  3. Get the resourcePickerUI field and create an instance of ResourcePickerUI dialog. It is the dialog that you should change. The dialog contains some TableLayoutPanel. You should insert a TextBox in a suitable place and handle its TextChanged event and filter the values which is showing in the ListBox. All controls have names and you can simply access to them and change their properties and values.

更改表格后,将其分配为resourcePickerUI.这样,编辑器将使用更改后的表单并显示您需要的内容.

After changing the form, assign it resourcePickerUI. This way, the editor will use the changed form and will show what you need.

实施

您可以在以下存储库中找到完整的工作示例:

You can find the full working example in the following repository:

下载zip

这是设计师的代码:

public class MyControlDesigner : ControlDesigner
{
    protected override void OnCreateHandle()
    {
        base.OnCreateHandle();
        var property = TypeDescriptor.GetProperties(this.Control)["BackgroundImage"];
        var resourceEditorSwitch = property.GetEditor(typeof(UITypeEditor)) as UITypeEditor;
        var editorToUseField = resourceEditorSwitch.GetType().GetProperty("EditorToUse",
            BindingFlags.NonPublic | BindingFlags.Instance);
        var editorToUse = editorToUseField.GetValue(resourceEditorSwitch);
        var resourcePickerUIField = editorToUse.GetType().GetField("resourcePickerUI",
            System.Reflection.BindingFlags.Instance |
            System.Reflection.BindingFlags.NonPublic);
        var resourcePickerUI = (Form)Activator.CreateInstance(resourcePickerUIField.FieldType);
        ModifyForm(resourcePickerUI);
        resourcePickerUIField.SetValue(editorToUse, resourcePickerUI);
    }
    void ModifyForm(Form f)
    {
        var resourceContextTableLayoutPanel = GetControl<TableLayoutPanel>(f, "resourceContextTableLayoutPanel");
        var resourceList = GetControl<ListBox>(f, "resourceList");
        resourceContextTableLayoutPanel.Controls.Remove(resourceList);
        var tableLayoutPanel = new TableLayoutPanel();
        tableLayoutPanel.Dock = DockStyle.Fill;
        tableLayoutPanel.Margin = new Padding(0);
        tableLayoutPanel.ColumnCount = 1;
        tableLayoutPanel.RowCount = 2;
        tableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.AutoSize));
        tableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 100));

        List<string> list = new List<string>();
        var textBox = new TextBox() { Dock = DockStyle.Fill, Margin = resourceList.Margin };
        Action<string> applyFilter = (s) =>
        {
            if (string.IsNullOrEmpty(s))
            {
                resourceList.BeginUpdate();
                resourceList.Items.Clear();
                resourceList.Items.AddRange(list.ToArray());
                resourceList.EndUpdate();
            }
            else
            {
                var list2 = list.Where(x => x.ToLower().StartsWith(s.ToLower())).ToList();
                resourceList.BeginUpdate();
                resourceList.Items.Clear();
                resourceList.Items.Add("(none)");
                resourceList.Items.AddRange(list2.ToArray());
                resourceList.EndUpdate();
            }
            if (resourceList.Items.Count > 1)
                resourceList.SelectedIndex = 1;
            else
                resourceList.SelectedIndex = 0;
        };
        var resxCombo = GetControl<ComboBox>(f, "resxCombo");
        resxCombo.SelectedValueChanged += (s, e) =>
        {
            resxCombo.BeginInvoke(new Action(() =>
            {
                if (resourceList.Items.Count > 0)
                {
                    list = resourceList.Items.Cast<string>().ToList();
                    textBox.Text = string.Empty;
                }
            }));
        };
        textBox.TextChanged += (s, e) => applyFilter(textBox.Text);
        textBox.KeyDown += (s, e) =>
        {
            if (e.KeyCode == Keys.Up)
            {
                e.Handled = true;
                if (resourceList.SelectedIndex >= 1)
                    resourceList.SelectedIndex--;
            }
            if (e.KeyCode == Keys.Down)
            {
                e.Handled = true;
                if (resourceList.SelectedIndex < resourceList.Items.Count - 1)
                    resourceList.SelectedIndex++;
            }
        };
        tableLayoutPanel.Controls.Add(textBox, 0, 0);

        resourceList.EnabledChanged += (s, e) =>
        {
            textBox.Enabled = resourceList.Enabled;

        };
        tableLayoutPanel.Controls.Add(resourceList, 0, 1);
        resourceContextTableLayoutPanel.Controls.Add(tableLayoutPanel, 0, 4);
    }
    T GetControl<T>(Control c, string name)
        where T : Control
    {
        return (T)c.Controls.Find(name, true).FirstOrDefault();
    }
}

这篇关于Visual Studio“选择资源"对话框替换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆