Отладчик Visualizer Winform ToolStripDropDownMenu ComboBox показывает элементы только при первом отображении - PullRequest
1 голос
/ 08 мая 2020

У меня есть проект визуализатора отладчика Visual Studio, и когда я добавляю ToolStripComboBox к ToolStripDropDownMenu, элементы поля со списком появляются только при первом отображении формы.

Вот так:

enter image description here

Самая основная c версия кода winform, показывающая проблему, такова:

public class MyVisualizerDialog : Form
{
    public MyVisualizerDialog()
    {
        var toolStripComboBox = new ToolStripComboBox
        {
            Items = { "One", "Two", "Three" }
        };

        var toolStripDownDown = new ToolStripDropDownMenu
        {
            Items = { toolStripComboBox }
        };

        var toolStrip = new ToolStrip
        {
            Items =
            {
                new ToolStripMenuItem("Options")
                {
                    DropDown = toolStripDownDown
                }
            }
        };

        Controls.Add(toolStrip);
    }
}

Тогда код визуализатора просто:

public class MyVisualizer : DialogDebuggerVisualizer
{
    protected override void Show(
        IDialogVisualizerService windowService,
        IVisualizerObjectProvider objectProvider)
    {
        windowService.ShowDialog(
            new MyVisualizerDialog());
    }
}

Некоторые дополнительные сведения:

  • Если я добавлю ToolStripComboBox к ToolStripMenuItem.DropDownItems, он будет работать нормально - кажется, это конкретно проблема с наличием ToolStripComboBox в ToolStripDropDown.

  • Если я создаю и открываю несколько экземпляров одного и того же класса формы в консольном приложении, он работает нормально.

  • Как только проблема возникает, она продолжает возникать - даже когда я возвращаю код к версии без ToolStripDropDown

  • Если я перезапустите Visual Studio, он работает в первый раз, когда форма отображается, а затем нет.

Есть идеи ?! Кто-нибудь знает какие-то морщинки в том, как IDialogVisualizerService размещает элементы управления или что-то в этом роде?!

Спасибо за чтение :)

1 Ответ

1 голос
/ 09 мая 2020

Похоже, что когда визуализатор отладчика закрывается, что обрабатывается на стороне отладчика, а не на стороне отладчика, DropDown уничтожается, но ToolStripManager не знает об этом и находит сам с недопустимым дескриптором, с которым он не знает, как управлять.

Поскольку ToolStripManager также активен в режиме разработки, это распространяет проблему на весь интерфейс дизайнера: вы можете обнаружить, что некоторые элементы DropDown все еще работают после закрытия визуализатора отладчика, но вы не сможете добавить другие элементы ToolStripComboBox где угодно.
Если вы настаиваете на , то и те, которые казались работающими, могут больше не работать.

Обратите внимание, что это неправильное поведение может быть преобразовано в объекты ComboBox; не напрямую, а когда вы пытаетесь получить доступ к их коллекции Items через интерфейс.
Это также может помешать компиляции проекта.

Явное удаление объекта Form, созданного на стороне визуализатора отладчика, может частично решить проблему на стороне отладчика, но не, как оказалось, на стороне визуализатора отладчика.

Простое решение - не устанавливать объект DropDown для ToolStripMenuItem и использовать вместо него MenuStrip, добавляя Items в ToolStripDownDown.


Создание пользовательских визуализаторов данных
Вопросы безопасности визуализатора


Образец визуализатора отладчика (простой визуализатор изображений) для тестирования поведение хорошее и плохое .

► Создайте проект библиотеки классов, для Target Framework установите профиль .Net Framework, AnyCPU.

► Добавьте ссылку на [Visual Studio install Path]\Common7\IDE\PublicAssemblies\Microsoft.VisualStudio.DebuggerVisualizers.dll и System.Windows.Forms.

► Скомпилируйте .dll как Release.

► Скопируйте .dll в каталог \Common7\Packages\Debugger\Visualizers текущего пути установки Visual Studio.

► Запустите сеанс отладки, добавьте точку останова, в которой установлено / загружено свойство Image / Bitmap, и используйте инструмент лупы, чтобы открыть предварительный просмотр.

using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.VisualStudio.DebuggerVisualizers;

[assembly: DebuggerVisualizer(
    typeof(ImageVisualizer.DebuggerSide), 
    typeof(VisualizerObjectSource), Target = typeof(Image), Description = "Test Visualizer")]
namespace TestVisualizer
{
    public class DebuggerSide : DialogDebuggerVisualizer
    {
        override protected void Show(IDialogVisualizerService windowService, IVisualizerObjectProvider objectProvider)
        {
            var image = (Image)objectProvider.GetObject();
            var form = new Form();
            form.ClientSize = new Size(image.Width, image.Height);
            form.FormBorderStyle = FormBorderStyle.FixedSingle;
            form.SuspendLayout();

            // -------   WORKING CODE   ---------------
            var menuStrip = new MenuStrip() { };
            var tsComboBox = new ToolStripComboBox { Items = { "One", "Two", "Three" } };
            var toolStripDownDown = new ToolStripMenuItem() { Text = "Options" };
            toolStripDownDown.DropDownItems.AddRange(new ToolStripItem[] { tsComboBox });
            menuStrip.Items.AddRange(new ToolStripItem[] { toolStripDownDown });
            // -------   WORKING CODE   ---------------

            // -------   BAD CODE   ---------------
            //var toolStripComboBox = new ToolStripComboBox { Items = { "One", "Two", "Three" } };
            //var toolStripDownDown = new ToolStripDropDownMenu { Items = { toolStripComboBox } };
            //var toolStrip = new ToolStrip {
            //    Items = { new ToolStripMenuItem("Options") { DropDown = toolStripDownDown } }
            //};

            // -------   BAD CODE   ---------------

            var pBox = new PictureBox() { Image = image, Dock = DockStyle.Fill };

            //form.Controls.Add(toolStrip);
            form.Controls.Add(menuStrip);
            form.Controls.Add(pBox);
            form.MainMenuStrip = menuStrip;
            form.ResumeLayout(false);
            form.PerformLayout();

            windowService.ShowDialog(form);
            form?.Dispose();
        }
    }
}
...