Исключение Конструктора WinForms


Форма WinForms, включающая UserControl, создает исключение, когда я пытаюсь отобразить ее в режиме конструктора, но работает правильно, когда программа запущена или отлажена.

Дизайнер говорит:

FpInfoA переменной '' либо недекларированных или никогда не был назначен.
ResearchTool fMain.Дизайнер.строка cs: 282 столбец: 1 Стек Вызовов
в системе.ComponentModel.Дизайн.Сериализация.CodeDomSerializerBase.Ошибка (менеджер IDesignerSerializationManager, строка exceptionText, строка helpLink) в системе.ComponentModel.Дизайн.Сериализация.CodeDomSerializerBase.DeserializeExpression (менеджер IDesignerSerializationManager, имя строки, выражение CodeExpression) в системе.ComponentModel.Дизайн.Сериализация.CodeDomSerializerBase.DeserializeExpression (менеджер IDesignerSerializationManager, имя строки, выражение CodeExpression) в системе.ComponentModel.Дизайн.Сериализация.CodeDomSerializerBase.DeserializeStatement(IDesignerSerializationManager менеджер, заявление CodeStatement)

Однако, похоже, что переменная назначена так, как я ожидал бы в InitializeComponent

private void InitializeComponent()
{
    // ... (Order of statements is same as in actual code) ...
    this.tpFpA = new System.Windows.Forms.TabPage();
    this.fpInfoA = new ResearchTool.FPInfo();
    // ...
    this.tpFpA.Controls.Add(this.fpInfoA); // THIS LINE BLOWS UP IN DESIGN MODE
}

Мысли о том, как отследить эту проблему? Например, есть ли способ отладки инициализации конструктора?

3 3

3 ответа:

Вы найдете информацию о том, как отслеживать выполнение кода во время разработки по адресу:

Какая информация необходима для устранения проблемы, которая возникает с вашими продуктами во время разработки?

Один обходной путь в случае, если вы не можете исправить проблему, будет заключаться в том, чтобы окружить оскорбляющие биты кода проверками на DesignMode.

Как в:

private void InitializeComponent()
{
    ...
    if(!DesignMode)
    {
        this.fpInfoA = new ResearchTool.FPInfo();
    }
    ...
}

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

Как сказал Ханс Ольссон , это потенциально можно решить, проверив режим проектирования и отключив нарушающую логику.

Эта ошибка также сработает, если есть какие-либо проблемы с конструктором вашего UserControl. Если при создании экземпляра UserControl конструктором возникнет исключение, то он завершится ошибкой. В моем случае неудача привела к тому же " [...] либо не объявлена, либо никогда не назначалась " ошибка.

Например, см. пользовательский контроль:

public class MyUserControl : UserControl {

    public MyUserControl()
    {
        InitializeComponent();

        throw new Exception(); //Causes a designer error.
    }
}
Теперь, наблюдая за конструктором для формы, содержащей это MyUserControl, мы увидим нечто подобное следующему:

Ошибка Конструктора Winforms

Я не могу сказать, похож ли конструктор на предыдущие версии Visual Studio; но что касается Visual Sutdio 2017, вы можете ясно видеть, что произошло.

Конструктор потерпел неудачу, потому что был брошен System.Exception. В результате переменная [REDACTED] считалась необъявленной или никогда не присваивалась, когда на самом деле автоматически сгенерированный код конструктора был правильным. Проблема была с конструктором MyUserControl.

Теперь, если вам нужно поместить логику, которая зависит от внешних служб/ресурсов, в конструктор элемента управления, вы должны указать, что это должно происходить только во время выполнения. Кроме того, вы можете предоставить ресурсы макета для времени разработки.

Для этого вы можете использовать LicenseManager и проверить его текущий UsageMode. Приведенный ниже модифицированный код теперь только создает исключение во время выполнения, и у дизайнера больше нет ошибки.

public class MyUserControl : UserControl {

    public MyUserControl()
    {
        InitializeComponent();

        if (LicenseManager.UsageMode != LicenseUsageMode.Designtime)
        {
            throw new Exception(); //No longer fails in design-time.
        }
    }
}