Как использовать привязку данных с переключателями Windows Forms? - PullRequest
9 голосов
/ 05 декабря 2008

У меня есть двоичное поле в моей базе данных, которое трудно описать в пользовательском интерфейсе с помощью одного флажка типа «XXXX?». Я бы предпочел использовать пару радиокнопок (например, «Сделай это способом Foo» и «Сделай это способом Bar»), но сейчас все остальные поля в моей форме привязаны к бизнес-объекту. Я бы тоже хотел связать пару радио-кнопок с бизнес-объектом, но пока не нашел хорошего способа сделать это. Я могу привязать одну из кнопок к полю, чтобы поле было установлено в «true», если кнопка выбрана, но при выборе другой кнопки отменяется выбор первой (т. Е. Две переключатели правильно спарены ), значение поля не обновляется, чтобы отразить это.

Я бы хотел сказать

button1.DataBindings.Add(new Binding("checked", source, "useFoo"));
button2.DataBindings.Add(new Binding("checked", source, "!useFoo"));

но я вполне уверен, что бросит, когда он запустится. Есть ли более простой способ, или я должен просто подумать над тем, как обозначить один флажок? Я не хочу добавлять дополнительные функции для обработки чего-то такого тривиального ...

ETA: комментатор предложил рассмотреть раскрывающийся список (ComboBox). Я думал об этом, но как мне связать это с логическим полем в базе данных / свойством в бизнес-объекте? Если я свяжу SelectedItem со свойством useFoo, что будет в коллекции Items? Должен ли я добавить только «True» и «False» или я могу каким-то образом добавить объект пары ключ / значение, который связывает отображаемый элемент («Use Foo» / «Do Not Use Foo») с логическим значением, стоящим за ним? У меня проблемы с поиском документов по этому вопросу.


Об ответе: решение, которое я использовал, заключалось в модификации бизнес-объекта - основная идея очень похожа на ту, которая была опубликована Gurge, но я придумал ее отдельно, прежде чем прочитать его ответ. Короче говоря, я добавил отдельное свойство, которое просто возвращает !useFoo. Одна радиокнопка привязана к source.UseFoo, а другая - к source.UseBar (имя нового свойства). Важно убедиться, что новое свойство имеет как геттеры, так и сеттеры, иначе вы получите действительно странное поведение.

Ответы [ 6 ]

7 голосов
/ 16 сентября 2009
  1. Привязать RadioButton, который напрямую связан с вашим логическим значением (т.е. проверяется, когда значение равно true).
  2. Добавьте обработчик события к событию CheckedChanged для этого RadioButton, который выглядит следующим образом:

    private void radioButton_CheckedChanged(object sender, EventArgs e)
    {
        foreach (Binding b in ((Control)sender).DataBindings)
            b.WriteValue();
    }
    
1 голос
/ 23 мая 2017

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

        // Load radio state
        radioButton1.Checked = ((myModel)myBindingSource.DataSource).boolOption1;
        radioButton2.Checked = ((myModel)myBindingSource.DataSource).boolOption2;

-

        // Save radio state
        ((myModel)myBindingSource.DataSource).boolOption1 = radioButton1.Checked;
        ((myModel)myBindingSource.DataSource).boolOption2 = radioButton2.Checked;

Я пытался перетащить элементы с панели «Источники данных» в Visual Studio 2015, когда я определил свои радиокнопки как логические значения в таблице, но есть проблемы с тем, что логические значения не обновляются до «ложь» при выборе другого радиокнопки. При переключении «argumentsValidation» на false радиокнопки автоматически отключаются при переходе между другими полями ввода текста.

1 голос
/ 31 марта 2016

Я столкнулся с той же проблемой и обнаружил, что это возможно при стандартной привязке данных:

button1.DataBindings.Add(new Binding("checked", source, "useFoo", false, DataSourceUpdateMode.OnPropertyChanged);
// no need to databind button 2, since button1.checked 
// is set to false when button2 is checked

По умолчанию DataSourceUpdateMode установлено на OnValidation. При установке значения OnPropertyChanged изменение немедленно распространяется на объект с привязкой к данным.

Мой бизнес-объект реализует INotifyPropertyChanged;

Протестировав это решение, я обнаружил, что мое событие OnPropertyChanged сработало дважды, когда я нажимал button2. Чтобы предотвратить это, просто установите

button1.CausesValidation = false;
button2.CausesValidation = false;

как показано здесь: TextBox приводит к тому, что PropertyChanged запускается дважды

1 голос
/ 18 декабря 2008

Если ваш бизнес-объект реализует INotifyPropertyChanged (что делает привязку более удобной), вы можете добавить следующий код в визуальный интерфейс, где BO - это ваш бизнес-объект, и он объявлен как withevents, а BO.Value - это логическое свойство, которое вы хотели бы привязать к.

Public Property NotValue() As Boolean
    Get
        Return Not BO.Value
    End Get
    Set(ByVal value As Boolean)
        BO.Value = Not value
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("NotValue"))
    End Set
End Property


Private Sub BO_PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Handles BO.PropertyChanged
    If e.PropertyName = "Value" Then
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("NotValue"))
    End If
End Sub

Следующие привязки подключат радиокнопки.

RBTrue.DataBindings.Add(New Binding("Checked", Me.BO, "Value", False, DataSourceUpdateMode.OnPropertyChanged))
RBFalse.DataBindings.Add(New Binding("Checked", Me, "NotValue", False, DataSourceUpdateMode.OnPropertyChanged))

Визуальный интерфейс также должен реализовывать INotifyPropertyChanged. Этот метод работает в обоих направлениях: исходное значение обновляется при изменении интерфейса и при изменении исходного значения интерфейс будет обновляться правильно.

1 голос
/ 06 декабря 2008

Я нашел способ сделать это, используя DataSet / DataTable.

Я создаю вычисляемый столбец в DataTable с выражением IIF(Foo=true, false, true). Давайте назовем этот столбец Bar.

Bar имеет тип Boolean. Теперь вы можете привязать один RadioButton.Checked к Foo и один к Bar.

Чтобы получить Bar проверку / снятие отметки для распространения на Foo, вы должны перейти к сгенерированному коду DataTable и добавить одну строку, последнюю в этом примере:

[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public bool Bar {
    get {
        try {
            return ((bool)(this[this.tableradio.BarColumn]));
        }
        catch (global::System.InvalidCastException e) {
            throw new global::System.Data.StrongTypingException("The value for column \'Bar\' in table \'radio\' is DBNull.", e);
        }
    }
    set {
        this[this.tableradio.BarColumn] = value;
        this[this.tableradio.FooColumn] = !value;
    }
}
0 голосов
/ 06 декабря 2008

Вам следует привязать только один из элементов управления, если вы уверены, что они находятся в одной группе.

Вы также можете рассмотреть DropDown.

...