Пользовательские свойства, определенные в базовой форме, теряют свое состояние в унаследованной форме при перестроении - PullRequest
5 голосов
/ 29 июля 2011

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

Окружающая среда:

  • Visual Studio 2010 Ultimate с пакетом обновления 1: версия 10.0.40219.1 SP1Rel
  • .Net Framework: версия 4.0.30319 SP1Rel
  • Windows 7 Ultimate

Ниже приведен исходный код и шаги для воспроизведения:

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

namespace Test
{
    public partial class BaseForm : Form
    {
        [DefaultValueAttribute(true)]
        public bool ControlVisible
        {
            get
            {
                return this.checkBox1.Visible;
            }
            set
            {
                this.checkBox1.Visible = value;
            }
        }

        [DefaultValueAttribute(false)]
        public bool ControlChecked
        {
            get
            {
                return this.checkBox1.Checked;
            }
            set
            {
                this.checkBox1.Checked = value;
            }
        }

        public BaseForm()
        {
            InitializeComponent();
        }
    }
}

В приведенном выше описании свойства по умолчанию совпадают с [DefaultValueAttribute], т. Е. В InitializeComponent () checkBox1.Visible имеет значение true, а checkBox1.Checked - false. Это настройки по умолчанию для элемента управления при перетаскивании на форму.

Затем я создал следующую унаследованную форму:

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

namespace Test
{
    public partial class Form1 : BaseForm
    {
        public Form1()
        {
            InitializeComponent();
        }
    }
}

Проблема и шаги по воспроизведению:

  1. Когда я открываю Form1 в конструкторе, свойства находятся в следующем состоянии.

    Состояние: ControlChecked = False - ControlVisible = True (полужирный)

    ControlVisible установлен на True , как и ожидалось, однако он выделен жирным шрифтом. [DefaultValueAttribute] имеет значение true в базовой форме, поэтому я ожидал, что это свойство не будет выделено жирным шрифтом.

  2. Теперь я изменяю ControlVisible на False в конструкторе. Жирный цвет отключается.

    Состояние: ControlChecked = False - ControlVisible = False

  3. Теперь я перестраиваю проект, и код в Form1 восстанавливается. Свойство ControlVisible возвращается к True , выделенному жирным шрифтом.

    Состояние: ControlChecked = False - ControlVisible = True (полужирный)

  4. Теперь я изменяю ControlChecked с False на True и становится жирным, как и ожидалось.

    Состояние: ControlChecked = True (полужирный) - ControlVisible = True (полужирный)

  5. Я перестраиваю проект без изменений.

    Состояние: ControlChecked = True (полужирный) - ControlVisible = True (полужирный)

  6. Теперь я изменяю свойство ControlVisible с True на False и заново собираю проект. ControlVisible перевернуто на True жирным шрифтом.

    Состояние: ControlChecked = True (полужирный) - ControlVisible = True (полужирный)

ControlChecked работает должным образом. ControlVisible продолжает переключаться обратно на True , когда для него установлено значение false, а жирный шрифт переворачивается Мне кажется, что каким-то образом [DefaultAttributeValue] true в базовой форме не распознается.

Обновление: Пересмотрено, чтобы исправить ошибку и точнее изолировать проблему.

Обновление: Если я установлю checkBox1.Visible = false в конструкторе BaseForm, то все будет работать как положено. Итак, нижняя строка показывает, что проблема заключается в том, что DefaultValueAttribute true распознается в пользовательском свойстве в унаследованной форме.

Ответы [ 2 ]

4 голосов
/ 29 июля 2011

Ваше свойство ControlVisible всегда имеет значение false:

    [DefaultValueAttribute(true)]
    public bool ControlVisible
    {
        get
        {
            return this.checkBox1.Visible;
        }
        set
        {
            this.checkBox1.Visible = false;
        }
    }

Ваш заданный метод должен быть:

    this.checkBox1.Visible = value;
2 голосов
/ 29 июля 2011

Ваш checkBox1 частный в базовом классе?Если это не так, то так и должно быть, потому что дизайнер сериализует оба установщика (один для checkBox1.Visible, а другой для ControlVisible), и только порядок сериализации будет определять конечное состояние, что плохо.

Также посмотрите на автоматически сгенерированный метод InitializeControls в файле Form1.designer.cs, явно ли он устанавливает для пользовательских свойств значения по умолчанию?

Наконец, попробуйте использовать ShouldSerialze и Reset и посмотри, у тебя другое поведение.

Редактировать

Я заново создал проблему и подключил один экземпляр VS для отладки другого.В первый раз, когда свойство ControlVisible было оценено VS, оно вернуло false, потому что checkBox1.Visible (источник получения) был false.Когда фактический элемент управления флажок был создан и показан, а окно свойств было прокручено для отображения ControlVisible, его значение было снова оценено и возвращено true , которое является значением по умолчанию, однако кажется, что VS внутренне уже помеченэто свойство изменено, так как его начальное значение отличается от значения по умолчанию.Это может быть ошибка в VS.

Я создал простую демонстрацию эффекта:

    public BaseForm()
    {
        InitializeComponent();
        _testValue = false;
    }

    private bool _testValue;

    [DefaultValue(true)]
    public bool TestProperty
    {
        get { return _testValue; }
        set { _testValue = value; }
    }

    protected override void OnVisibleChanged(EventArgs e)
    {            
        _testValue = true;
        base.OnVisibleChanged(e);
    }
}

При наследовании вышеуказанного BaseForm TestPropery ведет себя точно так же, как ControlVisible в вашем примере, поэтому ядумаю, что это ошибка в VS.

Решение вашей проблемы - использовать простое вспомогательное поле bool в качестве помощника, поскольку checkBox1.Visible ненадежен:

    public BaseForm()
    {
        InitializeComponent();
        checkBox1.Visible = _controlVisible = true;
    }

    private bool _controlVisible;

    [DefaultValue(true)]
    public bool ControlVisible
    {
        get { return _controlVisible; }
        set { _controlVisible = checkBox1.Visible = value; }
    }
...