Pregunta

Tengo un campo binario en mi base de datos que es difícil de describir en una interfaz de usuario usando una sola casilla de verificación tipo "¿Es XXXX?". Prefiero usar un par de botones de radio (por ejemplo, `` Hazlo a la manera Foo '' y `` Hazlo a la barra ''), pero en este momento todos los demás campos de mi formulario están vinculados a un objeto comercial. Me gustaría vincular también el par de botones de radio al objeto comercial, pero aún no he encontrado una buena manera de hacerlo. Puedo vincular uno de los botones al campo, de modo que el campo esté configurado como "verdadero" si se selecciona el botón, pero si selecciona el otro botón, deselecciona el primero (es decir, los dos botones de opción están correctamente emparejados), el valor del campo no se actualiza para reflejar esto.

Me gustaría poder decir

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

pero estoy bastante seguro de que arrojará cuando se ejecute. ¿Hay alguna manera más fácil, o debería pensar más en cómo redactar una casilla de verificación? No quiero agregar funciones adicionales para manejar algo tan trivial ...

ETA: un comentarista ha sugerido considerar un menú desplegable (ComboBox). Había pensado en esto, pero ¿cómo vincularía eso a un campo booleano en una base de datos / Propiedad en un objeto comercial? Si vinculo el SelectedItem a la propiedad useFoo, ¿qué iría en la colección Items? ¿Tendría que agregar solo " Verdadero " y " Falso " ;, ¿o podría de alguna manera agregar un objeto par clave / valor que vincule un elemento visualizado (" Use Foo " / " No usar Foo ") al valor booleano detrás de él? Tengo problemas para encontrar documentos sobre esto.


Acerca de la respuesta: la solución que utilicé implicaba modificar el objeto comercial: la idea básica es muy similar a la publicada por Gurge, pero se me ocurrió por separado antes de leer su respuesta. En resumen, agregué una propiedad separada que simplemente devuelve ! UseFoo . Un botón de opción está vinculado a source.UseFoo , y el otro está vinculado a source.UseBar (el nombre de la nueva propiedad). Es importante asegurarse de que la nueva propiedad tenga getters y setters, o terminará con un comportamiento realmente extraño.

¿Fue útil?

Solución

He encontrado una manera de hacerlo usando DataSet / DataTable.

Hago una columna calculada en el DataTable con la expresión IIF (Foo = true, false, true) . Llamemos a esa columna Bar .

Bar es de tipo booleano. Ahora puede vincular un RadioButton.Checked a Foo y uno a Bar .

Para que la Bar verifique / desmarque para propagarse de nuevo a Foo debe ir al código DataTable generado y agregar una línea, la última en esta muestra:

[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;
    }
}

Otros consejos

  1. Vincula el RadioButton que está directamente vinculado a tu valor booleano (es decir, se verifica cuando el valor es true ).
  2. Agregue un controlador de eventos al evento CheckedChanged en este RadioButton que tenga el siguiente aspecto:

    private void radioButton_CheckedChanged(object sender, EventArgs e)
    {
        foreach (Binding b in ((Control)sender).DataBindings)
            b.WriteValue();
    }
    

Si su objeto comercial implementa INotifyPropertyChanged (lo que hace que el enlace funcione mejor), puede agregar el siguiente código a la interfaz visual donde BO es su objeto comercial y se declara con los eventos y BO. El valor es la propiedad booleana a la que le gustaría unirse.

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

Los siguientes enlaces conectarán los botones de radio.

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

La interfaz visual también debe implementar INotifyPropertyChanged. Este método funciona en ambos sentidos: el valor original se actualiza si la interfaz cambia y si el valor original cambia, la interfaz se actualizará correctamente.

Me encontré con el mismo problema y descubrí que en realidad es posible con el enlace de datos estándar:

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

Por defecto, DataSourceUpdateMode está configurado en OnValidation . Al establecerlo en OnPropertyChanged , el cambio se propaga inmediatamente al objeto enlazado a datos.

Mi objeto empresarial implementa INotifyPropertyChanged ;

Al probar esta solución, descubrí que mi evento OnPropertyChanged se activó dos veces cuando hacía clic en button2 . Para evitar esto, simplemente configure

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

como se muestra aquí: La ausencia de TextBox hace que PropertyChanged sea despedido dos veces

Hazlo manualmente en código. Cuando cargue el formulario, configure sus botones de radio de acuerdo con su base de datos. Cuando presiona un " guardar " botón almacenar de estado como desee. Este ejemplo almacena radios como campos de bits en la base de datos.

        // 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;

Traté de arrastrar elementos desde " Fuentes de datos " panel en Visual Studio 2015 cuando definí mis botones de radio como booleanos en la tabla, pero hay problemas con los booleanos que no se actualizan a falso cuando se selecciona otro botón de radio. Cuando se cambian las '' causas Validación '' a falsos botones de radio desmarcados automáticamente al saltar entre otros campos de entrada de texto.

Solo deberías vincular uno de los controles siempre que te asegures de que estén en el mismo grupo.

También podría considerar un DropDown.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top