Правила времени разработки .NET Windows Forms - PullRequest
10 голосов
/ 11 ноября 2008

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

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

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

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

Ответы [ 5 ]

12 голосов
/ 19 февраля 2011

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

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

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

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

11 голосов
/ 12 ноября 2008

Вы можете проверить 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 голосов
/ 19 февраля 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 устанавливается только для элементов управления, созданных самим дизайнером.

2 голосов
/ 16 июня 2009

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

0 голосов
/ 11 ноября 2008

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...