Visual Studio“选择资源”对话框替换

在我的项目中,我有超过750个图像资源。 使用VS内置的“选择资源”对话框是一个噩梦,可以找到并选择一个图像 – 比方说 – 用于winforms设计器中的按钮。

如果它是一些像对话框这样的浏览器并且缺乏搜索function,它会更有用。

  • 你知道怎么替换这个对话框吗?

  • 有没有可以做到的扩展?

  • 如果没有这样的扩展,我会创建一个扩展/加载项,无论我需要做什么。 如果可以完成,你有任何真实的经验吗?

  • 我以为我会找到合适的dll并扩展它的beaviour,但不幸的是我找不到哪个dll包含这个悲剧

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

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

由于类的实现与Visual Studio程序集的其他内部类紧密耦合,因此很难提取类源代码并对其进行自定义,但是您拥有有关该类的信息将有助于我们查看其源代码代码,让我们获得有关该类的更多信息。

要自定义“ 资源选择”对话框,您可以在设计时获取该类的实例,并在显示对话框之前,使用代码操作对话框以具有类似于gif的过滤function, 注意我添加到的TextBox对话:

在此处输入图像描述

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

为此,您应该:

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

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

履行

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

  • R-aghaei / CustomizeSelectResourceDialog

  • 下载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(f, "resourceContextTableLayoutPanel"); var resourceList = GetControl(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 list = new List(); var textBox = new TextBox() { Dock = DockStyle.Fill, Margin = resourceList.Margin }; Action 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(f, "resxCombo"); resxCombo.SelectedValueChanged += (s, e) => { resxCombo.BeginInvoke(new Action(() => { if (resourceList.Items.Count > 0) { list = resourceList.Items.Cast().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(Control c, string name) where T : Control { return (T)c.Controls.Find(name, true).FirstOrDefault(); } }