2008-12-05 11 views
8

Tengo un campo binario en mi base de datos que es difícil de describir en una interfaz de usuario con una única casilla de verificación tipo "¿Es XXXX?". Prefiero usar un par de botones de radio (por ejemplo, "Hazlo a la manera de Foo" y "Hazlo a la manera de Bar"), pero ahora todos los demás campos de mi formulario están vinculados a un objeto de negocio. También me gustaría vincular los dos botones de radio al objeto comercial, pero todavía no se me ocurrió 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 al seleccionar el otro botón se deselecciona el primero (es decir, los dos botones de radio están emparejados correctamente)), el valor del campo no se actualiza para reflejar esto.¿Cómo uso el enlace de datos con los botones de radio de Windows Forms?

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 va a tirar cuando se ejecuta. ¿Hay una manera más fácil, o debería poner más pensamiento en cómo redactar una sola 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 los datos 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 de par clave/valor que vincule un elemento mostrado ("Usar Foo"/"No usar Foo") con el valor booleano detrás de él? Tengo problemas para encontrar documentos sobre esto.


Acerca de la respuesta: la solución terminé usando involucrada la modificación del objeto de negocio - 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 radio 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.

Respuesta

1

He encontrado una forma de hacerlo usando DataSet/DataTable.

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

La barra es del tipo Boolean. Ahora puede vincular un radiobutton.checked a Foo y uno a Bar.

Para obtener Bar marcando/desmarcando para propagar de nuevo a Foo debe ir al código DataTable generado y añadir 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; 
      } 
     } 
+2

¡Y no olvide hacer este cambio de nuevo cada vez que edite su DataSet! :-( – Mac

-3

Solo debe obligar a uno de los controles siempre que se asegure de que estén en el mismo grupo.

También podría considerar un DropDown.

+1

Pruebe esto: haga un par de botones de radio y una casilla de verificación, y enlace un botón de opción y la casilla de verificación con la misma propiedad booleana bajo un bindingsource. Marque la casilla de verificación y active las radios: no pasa nada. Ahora, si * un * marca la casilla de verificación, luego alternar, puede activarla, pero nunca desactivarla. – Coderer

1

Si su objeto de negocio implementa INotifyPropertyChanged (que hace que el trabajo vinculante sea más agradable), puede agregar el siguiente código a la interfaz visual donde BO es su objeto comercial y se declara con events y BO.Value es la propiedad booleana a la que le gustaría vincularse.

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 de dos maneras: el valor original se actualiza si la interfaz cambia y si el valor original cambia la interfaz se actualizará correctamente.

5
  1. Enlazar el RadioButton que está directamente vinculada a su valor booleano (es decir, se comprueba cuando el valor es true).
  2. Agregar un controlador de eventos para el evento CheckedChanged en este RadioButton que se parece a lo siguiente:

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

me encontré con el mismo problema, y ​​descubrió 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 

De forma predeterminada, DataSourceUpdateMode se establece en OnValidation. Al establecerlo en OnPropertyChanged, el cambio se propaga inmediatamente al objeto de datos.

Mi objeto comercial implementa INotifyPropertyChanged;

Al probar esta solución, descubrí que mi evento OnPropertyChanged se activó dos veces cuando estaba haciendo clic en button2. Para evitar esto, basta con establecer

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

como se muestra aquí: TextBox leave causes PropertyChanged get fired twice

1

hacerlo de forma manual en el código. Cuando carga el formulario, configure sus botones de opción según su base de datos. Cuando presiona un botón "guardar" almacenar de estado como lo desee. Este ejemplo almacena radios como campos de bit 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; 

Me trataron de arrastrar elementos desde el panel "Fuentes de datos" en Visual Studio 2015, cuando definí mis botones de radio como booleanos en la mesa, pero hay problemas con los booleanos no siendo actualizado a falso cuando se selecciona otro botón de radio. Al cambiar el "causesValidation" a los falsos botones de radio desactivados automáticamente al saltar entre otros campos de entrada de texto.

Cuestiones relacionadas