Подтвердить что ты не робот

Правила времени разработки .NET Windows Forms

У меня есть объект, который запускает поток, открывает файл и ждет ввода от других классов. Когда он получает ввод, он записывает его на диск. В принципе, это класс безопасности данных, защищенный потоком...

Здесь странная часть. Когда я открываю форму в конструкторе (Visual Studio 2008), который использует объект, который создается файл. Он, очевидно, работает под процессом vhost времени разработки...

Честно говоря, я не смог воспроизвести проблему в другом проекте. Я не уверен, что правила для кода, который выполняется в дизайнере и коде, который этого не делает. Например, создание файла в конструкторе Windows Forms фактически не создает файл во время разработки...

Какое объяснение? Есть ли ссылка?

4b9b3361

Ответ 1

Вы можете проверить UsageMode LicenseManager, чтобы проверить, находится ли код во время разработки или нет.

System.ComponentModel.LicenseManager.UsageMode == System.ComponentModel.LicenseUsageMode.Designtime

Вот краткий пример:

using System;
using System.ComponentModel;
using System.Windows.Forms;

namespace Test
{
    public class ComponentClass : Component
    {
        public ComponentClass()
        {
            MessageBox.Show("Runtime!");
        }
    }
}

Когда этот компонент будет добавлен в вашу форму в конструкторе, вы немедленно получите окно сообщения.

Чтобы предотвратить это, вы можете добавить простой оператор if, чтобы проверить, не находится ли код во время разработки

using System;
using System.ComponentModel;
using System.Windows.Forms;

namespace Test
{
    public class ComponentClass : Component
    {
        public ComponentClass()
        {
            if (LicenseManager.UsageMode != LicenseUsageMode.Designtime)
            {
                MessageBox.Show("Runtime!");
            }
        }
    }
}

После добавления оператора if окно сообщения больше не появляется, когда компонент добавляется в форму через конструктор.

Надеюсь, это поможет.

-jeremy

Ответ 2

Конструктор элемента управления или формы не запускается при редактировании этого класса в конструкторе (и не вызывается OnLoad). Я иногда использовал это, чтобы установить одно значение в дизайнере (например, чтобы его дочерние элементы управляли всем Visible в дизайнере), но переопределить некоторые из них на другое значение по умолчанию в конструкторе (например, скрывать определенные дочерние элементы управления, которые будут показывать только в определенных обстоятельствах, таких как индикатор в строке состояния).

Однако конструктор выполняется, если элемент управления помещен как дочерний элемент в другой элемент управления или форму в конструкторе. OnLoad также выполняется. Это может случиться так, как ваш код регистрации случайно запускался в дизайнере.

Для определения дизайна и времени выполнения ответ на еще один вопрос имеет скриншоты некоторых эмпирических тестов, показывающих значения, возвращаемые некоторыми общими подходами. По-видимому, дочерний элемент управления дочернего элемента управления (два уровня вниз) формы или элемента управления, редактируемого в конструкторе, видит свой собственный DesignMode == false, поэтому проверка нормального свойства не сможет защитить код (например, в методе OnLoad ) для элементов управления, вложенных в элемент управления, добавленный в конструктор. Если вы проверяли DesignMode, как и следовало ожидать, это может быть вложенность, которая заставила его обойти эту проверку. Он также всегда видит конструктор DesignMode == false внутри конструктора.

Кроме того, обратите внимание, что проверка LicenseManager.UsageMode видит только DesignTime внутри конструктора; когда OnLoad называется, он находится в пределах RunTime LicenseContext. Наиболее полным решением, по-видимому, является проверка LicenseManager.UsageMode в конструкторе элемента управления или формы (или компонента) и сохранение этого параметра в переменной-члене или свойстве, которое вы можете проверить позже, чтобы избежать запуска кода, который никогда не должен запускаться в конструкторе даже когда они вложены. Также существует другой подход в другом ответе к этому другому вопросу, который учитывает вложенность, но работает только вне конструктора.

Ответ 3

Вы также можете использовать это, чтобы проверить, работает ли Visual Studio Designer код:

public static bool DesignMode
{
    get {  return (System.Diagnostics.Process.GetCurrentProcess().ProcessName == "devenv"); }
}

Затем в Form_Load:

if (!DesignMode)
{
    // Run code that breaks in Visual Studio Designer (like trying to get a DB connection)
}

Однако это менее элегантно, чем использование LicensManager.UsageMode, но оно работает (до тех пор, пока Microsoft не изменит имя процесса, за которым работает Visual Studio).

Ответ 4

Ну, так как это было воскрешено в любом случае, здесь функция, которую я использую, чтобы определить, находится ли я в режиме разработки:

public static bool IsAnyInDesignMode(Control control){
    while(control != null){
        if(control.Site != null && control.Site.DesignMode)
            return true;
        control = control.Parent;
    }
    return false;
}

Это обрабатывает случай, когда элемент управления является дочерним элементом, созданным другим элементом управления. Свойство DesignMode задается только для элементов управления, созданных самим дизайнером.

Ответ 5

Есть некоторые вещи, которые вы не должны делать с дизайнером. У меня нет никаких убедительных доказательств, но я обнаружил, что дизайнер Windows Forms ненавидит его, когда вы удаляете из него конструктор по умолчанию. Просто продолжайте и создавайте новые перегрузки, но оставьте пустой конструктор на месте.

Также старайтесь избегать выполнения Form_Load событий в базовых классах, которые вы наследуете.