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

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

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

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

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


person Nate    schedule 11.11.2008    source источник


Ответы (5)


Вы можете проверить 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 окно сообщения больше не появляется, когда компонент добавляется в форму через конструктор.

person Community    schedule 11.11.2008

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

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

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

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

person Rob Parker    schedule 18.02.2011

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

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

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

person P Daddy    schedule 19.02.2011

Вы также можете использовать это, чтобы проверить, выполняет ли код 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).

person tzup    schedule 16.06.2009
comment
Чувак, твой менее элегантный метод - единственный, который работает. LicensManager.UsageMode не работает, например. когда дизайнер вызывает метод получения свойства пользовательского элемента управления. - person Soonts; 10.06.2010

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

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

person Tigraine    schedule 11.11.2008