Пользовательские свойства пользовательского элемента управления теряют состояние при перестроении пользовательского элемента управления

#c# #winforms #user-controls #properties #custom-controls

#c# #winforms #пользовательские элементы управления #свойства

Вопрос:

У меня есть пользовательский элемент управления с пользовательскими свойствами следующим образом:

 [DefaultValue(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[Description("Gets or sets whether the "Remove" button is visible.")]
public bool ShowRemoveButton
{
    get
    {
        return this.removeButton.Visible;
    }
    set
    {
        this.removeButton.Visible = value;
    }
}
  

Элемент управления содержит стандартный элемент управления button. Это свойство используется для отображения или скрытия кнопки. Пользовательский элемент управления встроен в отдельную сборку проекта. Я поместил его в форму, и я могу устанавливать и отменять указанное выше свойство, и, похоже, все работает просто отлично. Однако, когда проект, содержащий пользовательский элемент управления, перестраивается, значение свойства меняется на «false», что не является значением по умолчанию.

Как я могу предотвратить потерю / изменение состояния пользовательского свойства при перестроении элемента управления?

Ответ №1:

Проблема в том, что DefaultValueAttribute только сообщает разработчику, какое значение по умолчанию для свойства. Он определяет, отображается ли свойство жирным шрифтом и какое значение сбрасывается, когда вы щелкаете правой кнопкой мыши по свойству и выбираете «Сброс» из контекстного меню.

Чего он не делает, так это присваивает свойству определенное значение во время выполнения. Для этого вам нужно поместить код в метод конструктора вашего пользовательского элемента управления. Например:

 // set default visibility
this.removeButton.Visible = true;
  

В противном случае, как вы описали, значение свойства будет сброшено при перестроении проекта. Он будет выделен жирным шрифтом в окне свойств конструктора, потому что он не соответствует значению по умолчанию (как указано в DefaultValueAttribute ), но этот атрибут не изменяет установленное значение.

Комментарии:

1. Я попробовал выше и установил «this.removeButton. Видимый = true» в конструкторе пользовательского элемента управления. Изначально казалось, что он сохраняет свое состояние. Перестроения без изменений не изменили значение свойства. Однако, когда я внес изменения в пользовательский элемент управления и перестроил его, свойство снова переключилось на «false» и выделилось жирным шрифтом. Это довольно раздражает.

2. @Elan: Тогда в вашем коде должно быть что-то, что изменяет значение. Я создал несколько повторно используемых библиотек элементов управления и пользовательских элементов управления, но у меня никогда не было проблем с этим. Выполните поиск в своем коде, чтобы узнать, есть ли у вас где-нибудь настройка removeButton.Visible свойства. Скорее всего, оно скрыто в *.Designer.cs файле, куда оно было автоматически вставлено, и вы его не видите.

3. Пользовательский элемент управления присваивает свойству значение «true» в конструкторе. Designer.cs основной формы — это код, генерирующий свойство «ShowRemoveButton» равным false. Это единственные два места. Я удалил атрибут [defaultValue(true)] в объявлении свойства пользовательского элемента управления в надежде, что присвоение свойству в основной форме значения «true» приведет к сохранению значения. Тем не менее, значение свойства «true» теряется при регенерации класса designer.cs и заменяется на «false». Я не могу установить значение «true». Это происходит после некоторых изменений дизайнера форм и перестройки.

4. @Elan: Если вы можете достоверно воспроизвести это, пожалуйста, рассмотрите возможность редактирования вашего вопроса, чтобы включить минимальный код, необходимый для этого другим пользователям. Я думаю, что понимаю, о чем вы говорите, но я не видел такого поведения раньше в моем собственном использовании. Я знаю, что есть несколько крайних случаев, когда дизайнер Visual Studio все усложнит, но я заинтересован в расследовании как можно большего их числа. Если я смогу воспроизвести это самостоятельно, я могу либо исправить это, либо отправить отчет об ошибке в Microsoft и сослаться на него здесь, чтобы другие могли подтвердить.

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

Ответ №2:

Простой способ предотвратить сброс свойств любых содержащихся элементов управления при (де) сериализации связанных свойств — использовать частное резервное поле для свойства и присвоить значение по умолчанию, которое соответствует параметру DefaultValue атрибута. В данном случае это _showRemoveButton = true объявление / назначение ниже.

 [DefaultValue(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[Description("Gets or sets whether the "Remove" button is visible.")]
public bool ShowRemoveButton
{
    get
    {
        return _showRemoveButton;
    }
    set
    {
        _showRemoveButton = value;
        this.removeButton.Visible = value;
    }
}
private bool _showRemoveButton = true;
  

Ответ №3:

Старый пост, но он привел меня к решению моей проблемы. У меня был почти тот же эффект, что состояние моего свойства было потеряно при перестроении. В моем случае свойство представляет собой сам класс, который предоставляет набор логических значений.

Для меня решением было изменить bevhaviour то, как дизайнеры serlializes свойство.

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public SomePropertyClass SomeProperty
{
    get { return _SomeProperty; }
    set { _SomeProperty = Value; }
}
  

С помощью DesignerSerializationVisibility.Содержимое вы указываете дизайнеру сериализовать содержимое класса свойств (мое логическое значение, содержащееся в SomePropertyClass), а не само свойство. Я предполагаю, что другим подходом было бы сделать SomePropertyClass сериализуемым, но описанный выше подход был быстрее реализован.

Возможно, это кому-то поможет. Sascha