Использование ApplicationSettings для хранения свойства Checked для WinForms RadioButtons

У меня есть диалоговое окно WinForms, содержащее 3 переключателя. Я использую ApplicationSettings для привязки свойства Checked каждого из этих RadioButton элементов управления, но он не выполняет то, что я от него ожидаю. Теперь мне нужно дважды щелкнуть каждый переключатель, прежде чем он будет проверен, и выбранный переключатель не сохраняется.

Есть ли строка кода, которую мне нужно выполнить при закрытии формы, которая сохраняет пользовательские настройки?

Как мне избавиться от необходимости дважды нажимать на переключатели?

Есть ли лучший способ сохранить этот тип пользовательских настроек? У меня есть общедоступное свойство в классе диалогового окна, которое получает / устанавливает значение перечисления в зависимости от того, какой переключатель установлен, но я не видел простого способа привязать это свойство к настройке пользователя.

Изменить: надо было указать, что я использую vb.net. Я думаю, это означает My.Settings вместо Properties.Settings.


person CoderDennis    schedule 01.06.2009    source источник


Ответы (4)


Я могу ответить на эту часть вашего вопроса:

Есть ли строка кода, которую мне нужно выполнить при закрытии формы, которая сохраняет пользовательские настройки?

Настройки приложения хранятся в вашем Settings классе в пространстве имен Properties. Класс Settings имеет статическое свойство с именем Default, которое представляет текущие настройки вашего приложения. Итак, в событии Closing вашей основной формы вы вызываете:

Properties.Settings.Default.Save();

... чтобы сохранить настройки.

Точно так же вы можете получить доступ к настройкам программно, используя имя настройки: Properties.Settings.Default.MyRadioButtonState (или как вы его назвали).

person Matt Hamilton    schedule 01.06.2009
comment
Спасибо! Это заставило меня двигаться в правильном направлении. В vb.net это My.Settings вместо Properties.Settings.Default, но в остальном он работает отлично. Теперь у меня есть только один параметр, и я использую общедоступное свойство формы в событиях Load и FormClosing. - person CoderDennis; 02.06.2009
comment
На моем компьютере нет необходимости сохранять настройки при закрытии. Они сохраняются автоматически. Проблема только в том, что мне нужно дважды щелкнуть. - person Geoffrey; 26.06.2010

Отвечаю на эту часть вашего вопроса:

Как мне избавиться от необходимости дважды нажимать на переключатели?

Вы можете добавить следующий обработчик событий к событию Click каждого из трех RadioButton (из которых свойства Checked привязаны к параметрам приложения) в вашем GroupBox:

Private Sub RadioButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tomRadioButton.Click, dickRadioButton.Click, harryRadioButton.Click
    If sender.Checked = False Then
        sender.Checked = True
    End If
End Sub

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

Причина проблемы была объяснена два года назад (в 2008 году) в разделе 5 документа Surviving WinForms Databinding в блоге Turbulent Intelect (спасибо, ohadsc за ссылку) :

Правило 5. Не привязывайтесь к интерактивным переключателям

Я знаю, как было бы здорово, если бы вы могли просто привязать кучу переключателей к свойству enum. Я действительно. Вы думаете, что просто подключите некоторые события Format и Parse, чтобы преобразовать их обратно в перечисление, и все будет хорошо. Было бы чертовски удобно, если бы это действительно работало. Но WinForms для этого не годится. Для трех полных выпусков сейчас (или это 3.5 релизы?) Так и было. Это из-за порядка событий, который MS не может изменить, не заставив тысячи разработчиков по-настоящему разозлиться.

Проблема действительно сводится к тому, что, в отличие от свойств данных других элементов управления, свойство Checked переключателя фактически не изменяется, пока фокус не покинет переключатель. И, как со всеми элементами управления WinForms, фокус фактически не покидает переключатель до тех пор, пока фокус не будет передан другому элементу управления, и фактически только после того, как сработает событие Click вновь сфокусированного элемента управления. Результатом этого, что касается переключателей, является то, что если вы попытаетесь выполнить привязку к ним, связанные свойства в вашем источнике данных фактически отстают от визуального состояния ваших переключателей на один щелчок. Если у вас есть только два переключателя, источник данных будет находиться точно напротив видимого состояния, пока вы не нажмете где-нибудь еще, что не запускает действие, которое ссылается на эти свойства источника данных. Что может сделать эту ошибку действительно раздражающей. Я почти подумал, что у меня галлюцинации.

Теперь, честно говоря, это возможно. Но это самый грязный клудж из всех, что когда-либо собирались. Ладно, может быть, это не так уж и плохо ... но это точно грязный хакер. Для того, чтобы то, что действительно уже должно быть доступно, нужно потрудиться. Насколько я могу судить, единственный способ решить эту проблему, не отказываясь от механизма привязки данных, - это, по сути, создать собственный элемент управления RadioButton с изменением свойств и порядком событий, которые действительно полезны. Вы можете написать один с нуля или создать подкласс RadioButton и переопределить всю логику событий с помощью настраиваемой обработки сообщений.

person Geoffrey    schedule 26.06.2010

Благодаря Джеффри Ван Вику и ohadsc (за ссылку) я придумал следующий настраиваемый элемент управления. По сути, это настраиваемый фрейм, который автоматически реализует код Джеффри для всех содержащихся в нем радиокнопок. Преимущество состоит в том, что теперь вы можете использовать ApplicationSettings для привязки проверенного свойства элемента управления, и оно будет работать так, как должно.

Вот мой код на C # для создания настраиваемого элемента управления:

 public partial class RadioPanel : System.Windows.Forms.Panel
    {
        protected override void OnControlAdded(ControlEventArgs e)
        {
            base.OnControlAdded(e);
            var radioButton = e.Control as RadioButton;
            if (radioButton != null)
                radioButton.Click += radioButton_Click;
        }

        void radioButton_Click(object sender, EventArgs e)
        {
            var radio = (RadioButton)sender;
            if (!radio.Checked)
                radio.Checked = true;
        }

    }
person user867501    schedule 02.08.2011

Это поведение объясняется в пункте 5 здесь:

http://turbulentintellect.blogspot.com/2008/07/surviving-winforms-databinding.html

Одним из возможных решений может быть собственный GroupGox: Лучший способ привязать группу радиокнопок в WinForms

person Ohad Schneider    schedule 06.03.2010
comment
Спасибо за ответ. Я забыл даже об этом вопросе! - person CoderDennis; 10.03.2010
comment
Не за что! Спасибо за вопрос :) - person Ohad Schneider; 11.03.2010