visual ejemplos ejemplo c# winforms data-binding radio-button

c# - ejemplos - La mejor forma de enlazar datos con un grupo de botones de radio en WinForms



radio button php ejemplo (9)

Actualmente estoy trabajando en la conexión de datos de algunas de mis formas existentes de Windows, y me he encontrado con un problema para encontrar la forma correcta de enlazar datos a un grupo de controles de botones de radio dentro de un cuadro de grupo.

Mi objeto comercial tiene una propiedad entera a la que quiero vincular con 4 botones de radio (donde cada uno de ellos representa los valores 0 - 3).

Actualmente estoy vinculando contra un objeto presentador que funciona como la carpeta entre el formulario y el objeto comercial, y la forma en que lo he hecho ahora es tener 4 propiedades separadas que cada uno se une a cada uno de estos valores (yo uso INotifyPropertyChanged , pero sin incluir eso aquí):

Private int _propValue; Public bool PropIsValue0 { get { return _propValue == 0; } set { if (value) _propValue = 0; } } Public bool PropIsValue1 { // As above, but with value == 1 } Public bool PropIsValue2 { // As above, but with value == 2 } Public bool PropIsValue3 { // As above, but with value == 3 }

Y luego ato cada uno de los botones de radio a sus respectivas propiedades como se indica arriba.

Esto no me parece correcto, por lo que cualquier consejo es muy apreciado.


Creo que usaría mi propio GroupBox. Me gustaría vincular el CustomGroupBox a su modelo y establecer el RadioButton correcto (utilizando la etiqueta o las propiedades del nombre) del valor binded.


Empecé a resolver la misma problemática.

Usé una clase RadioButtonBinding que encapsula todos los botones de radio sobre una enumeración en la fuente de datos.

Esta clase siguiente mantiene todos los botones de opción en una lista y realiza una búsqueda de la enumeración:

class RadioButtonBinding : ILookup<System.Enum, System.Windows.Forms.RadioButton> { private Type enumType; private List<System.Windows.Forms.RadioButton> radioButtons; private System.Windows.Forms.BindingSource bindingSource; private string propertyName; public RadioButtonBinding(Type myEnum, System.Windows.Forms.BindingSource bs, string propertyName) { this.enumType = myEnum; this.radioButtons = new List<System.Windows.Forms.RadioButton>(); foreach (string name in System.Enum.GetNames(this.enumType)) { System.Windows.Forms.RadioButton rb = new System.Windows.Forms.RadioButton(); rb.Text = name; this.radioButtons.Add(rb); rb.CheckedChanged += new EventHandler(rb_CheckedChanged); } this.bindingSource = bs; this.propertyName = propertyName; this.bindingSource.DataSourceChanged += new EventHandler(bindingSource_DataSourceChanged); } void bindingSource_DataSourceChanged(object sender, EventArgs e) { object obj = this.bindingSource.Current; System.Enum item = obj.GetType().GetProperty(propertyName).GetValue(obj, new object[] { }) as System.Enum; foreach (System.Enum value in System.Enum.GetValues(this.enumType)) { if (this.Contains(value)) { System.Windows.Forms.RadioButton rb = this[value].First(); if (value.Equals(item)) { rb.Checked = true; } else { rb.Checked = false; } } } } void rb_CheckedChanged(object sender, EventArgs e) { System.Windows.Forms.RadioButton rb = sender as System.Windows.Forms.RadioButton; System.Enum val = null; try { val = System.Enum.Parse(this.enumType, rb.Text) as System.Enum; } catch(Exception ex) { // cannot occurred if code is safe System.Windows.Forms.MessageBox.Show("No enum value for this radio button : " + ex.ToString()); } object obj = this.bindingSource.Current; obj.GetType().GetProperty(propertyName).SetValue(obj, val, new object[] { }); this.bindingSource.CurrencyManager.Refresh(); } public int Count { get { return System.Enum.GetNames(this.enumType).Count(); } } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return this.radioButtons.GetEnumerator(); } public bool Contains(Enum key) { return System.Enum.GetNames(this.enumType).Contains(key.ToString()); } public IEnumerable<System.Windows.Forms.RadioButton> this[Enum key] { get { return this.radioButtons.FindAll(a => { return a.Text == key.ToString(); }); } } IEnumerator<IGrouping<Enum, System.Windows.Forms.RadioButton>> IEnumerable<IGrouping<Enum, System.Windows.Forms.RadioButton>>.GetEnumerator() { throw new NotImplementedException(); } public void AddControlsIntoGroupBox(System.Windows.Forms.GroupBox gb) { System.Windows.Forms.FlowLayoutPanel panel = new System.Windows.Forms.FlowLayoutPanel(); panel.Dock = System.Windows.Forms.DockStyle.Fill; panel.FlowDirection = System.Windows.Forms.FlowDirection.RightToLeft; foreach (System.Windows.Forms.RadioButton rb in this.radioButtons) { panel.Controls.Add(rb); } gb.Controls.Add(panel); } }

Está utilizando la clase en un formulario al agregar ese código en el constructor del formulario:

public PageView() { InitializeComponent(); RadioButtonBinding rbWidth = new RadioButtonBinding(typeof(Library.EnumConstraint), this.pageBindingSource, "ConstraintWidth"); rbWidth.AddControlsIntoGroupBox(this.groupBox1); RadioButtonBinding rbHeight = new RadioButtonBinding(typeof(Library.EnumConstraint), this.pageBindingSource, "ConstraintHeight"); rbHeight.AddControlsIntoGroupBox(this.groupBox3); this.pageBindingSource.CurrentItemChanged += new EventHandler(pageBindingSource_CurrentItemChanged); }


Establezca el nombre de la etiqueta de sus botones de radio en algo que represente el valor.

Cree una configuración de cadena, por ejemplo, OptionDuplicateFiles, y asígnele el valor predeterminado del nombre de etiqueta para su botón de opción predeterminado.

Para guardar su botón de opción marcado:

Settings.Default.OptionDuplicateFiles = gbxDuplicateFiles.Controls .OfType<RadioButton>() .Where(b => b.Checked) .Select(b => b.Tag) .First() .ToString();

Para cargar su botón de opción marcado:

(gbxDuplicateFiles.Controls .OfType<RadioButton>() .Where(b => b.Tag.ToString() == Settings.Default.OptionDuplicateFiles) .First()) .Checked = true;

Tada!


Este es mi enfoque para enlazar una lista de botones de radio a una enumeración.

Usando el Enum como una cadena en la propiedad Tag del botón, utilizo el evento Binding.Format y Binding.Parse para decidir qué botón se debe marcar .

public enum OptionEnum { Option1 = 0, Option2 } OptionEnum _rbEnum = OptionEnum.Option1; OptionEnum PropertyRBEnum { get { return _rbEnum; } set { _rbEnum = value; RaisePropertyChanged("PropertyRBEnum"); } } public static void FormatSelectedEnum<T>(object sender, ConvertEventArgs args) where T : struct { Binding binding = (sender as Binding); if (binding == null) return; Control button = binding.Control; if (button == null || args.DesiredType != typeof(Boolean)) return; T value = (T)args.Value; T controlValue; if (Enum.TryParse(button.Tag.ToString(), out controlValue)) { args.Value = value.Equals(controlValue); } else { Exception ex = new Exception("String not found in Enum"); ex.Data.Add("Tag", button.Tag); throw ex; } } public static void ParseSelectedEnum<T>(object sender, ConvertEventArgs args) where T : struct { Binding binding = (sender as Binding); if (binding == null) return; Control button = binding.Control; bool value = (bool)args.Value; if (button == null || value != true) return; T controlValue; if (Enum.TryParse(button.Tag.ToString(), out controlValue)) { args.Value = controlValue; } else { Exception ex = new Exception("String not found in Enum"); ex.Data.Add("Tag", button.Tag); throw ex; } }

Luego configure su enlace de datos de esta manera:

radioButton1.Tag = "Option1"; radioButton2.Tag = "Option2"; foreach (RadioButtonUx rb in new RadioButtonUx[] { radioButton1, radioButton2 }) { Binding b = new Binding("Checked", this, "PropertyRBEnum"); b.Format += FormatSelectedRadioButton<OptionEnum>; b.Parse += ParseSelectedRadioButton<OptionEnum>; rb.DataBindings.Add(b); }


Lo que sigue es una implementación genérica de RadioGroupBox en el espíritu de la sugerencia de ArielBH (algunos códigos tomados del RadioPanel de Jay Andrew Allen). Simplemente agregue RadioButtons, establezca sus etiquetas en diferentes enteros y ligue a la propiedad ''Seleccionado''.

public class RadioGroupBox : GroupBox { public event EventHandler SelectedChanged = delegate { }; int _selected; public int Selected { get { return _selected; } set { int val = 0; var radioButton = this.Controls.OfType<RadioButton>() .FirstOrDefault(radio => radio.Tag != null && int.TryParse(radio.Tag.ToString(), out val) && val == value); if (radioButton != null) { radioButton.Checked = true; _selected = val; } } } protected override void OnControlAdded(ControlEventArgs e) { base.OnControlAdded(e); var radioButton = e.Control as RadioButton; if (radioButton != null) radioButton.CheckedChanged += radioButton_CheckedChanged; } void radioButton_CheckedChanged(object sender, EventArgs e) { var radio = (RadioButton)sender; int val = 0; if (radio.Checked && radio.Tag != null && int.TryParse(radio.Tag.ToString(), out val)) { _selected = val; SelectedChanged(this, new EventArgs()); } } }

Tenga en cuenta que no puede vincularse a la propiedad ''Seleccionado'' a través del diseñador debido a problemas de orden de inicialización en InitializeComponent (la vinculación se realiza antes de que los botones de radio se inicialicen, por lo que su etiqueta es nula en la primera asignación). Así que solo únete a ti mismo así:

public Form1() { InitializeComponent(); //Assuming selected1 and selected2 are defined as integer application settings radioGroup1.DataBindings.Add("Selected", Properties.Settings.Default, "selected1"); radioGroup2.DataBindings.Add("Selected", Properties.Settings.Default, "selected2"); }


Me gustó la idea de RadioButtonGroupBox, pero decidí crear una versión que sea autosuficiente. No hay ninguna razón para agregar valor al atributo Etiqueta o para introducir nuevos atributos de valor. Cualquier botón de radio asignado sigue siendo miembro de RadioButtonGroupBox y la secuencia de botones de radio se define durante el desarrollo. Soo, modifiqué el código. Ahora puedo obtener y configurar el botón de radio seleccionado por posición de índice, Por nombre de control y por Texto. El texto BTW solo se puede utilizar si el texto asignado es diferente para cada botón de radio.

public class RadioButtonGroupBox : GroupBox { public event EventHandler SelectedChanged = delegate { }; int _nIndexPosCheckRadioButton = -1; int _selected; public int Selected { get { return _selected; } } public int CheckedRadioButtonIndexPos { set { int nPosInList = -1; foreach (RadioButton item in this.Controls.OfType<RadioButton>()) { // There are RadioButtonItems in the list... nPosInList++; // Set the RB that should be checked if (nPosInList == value) { item.Checked = true; // We can stop with the loop break; } } _nIndexPosCheckRadioButton = nPosInList; } get { int nPosInList = -1; int nPosCheckeItemInList = -1; foreach (RadioButton item in this.Controls.OfType<RadioButton>()) { // There are RadioButtonItems in the list... nPosInList++; // Find the RB that is checked if (item.Checked) { nPosCheckeItemInList = nPosInList; // We can stop with the loop break; } } _nIndexPosCheckRadioButton = nPosCheckeItemInList; return _nIndexPosCheckRadioButton; } } public string CheckedRadioButtonByText { set { int nPosInList = -1; foreach (RadioButton item in this.Controls.OfType<RadioButton>()) { // There are RadioButtonItems in the list... nPosInList++; // Set the RB that should be checked if (item.Text == value) { item.Checked = true; // We can stop with the loop break; } } _nIndexPosCheckRadioButton = nPosInList; } get { string cByTextValue = "__UNDEFINED__"; int nPosInList = -1; int nPosCheckeItemInList = -1; foreach (RadioButton item in this.Controls.OfType<RadioButton>()) { // There are RadioButtonItems in the list... nPosInList++; // Find the RB that is checked if (item.Checked) { cByTextValue = item.Text; nPosCheckeItemInList = nPosInList; // We can stop with the loop break; } } _nIndexPosCheckRadioButton = nPosCheckeItemInList; return cByTextValue; } } public string CheckedRadioButtonByName { set { int nPosInList = -1; foreach (RadioButton item in this.Controls.OfType<RadioButton>()) { // There are RadioButtonItems in the list... nPosInList++; // Set the RB that should be checked if (item.Name == value) { item.Checked = true; // We can stop with the loop break; } } _nIndexPosCheckRadioButton = nPosInList; } get { String cByNameValue = "__UNDEFINED__"; int nPosInList = -1; int nPosCheckeItemInList = -1; foreach (RadioButton item in this.Controls.OfType<RadioButton>()) { // There are RadioButtonItems in the list... nPosInList++; // Find the RB that is checked if (item.Checked) { cByNameValue = item.Name; nPosCheckeItemInList = nPosInList; // We can stop with the loop break; } } _nIndexPosCheckRadioButton = nPosCheckeItemInList; return cByNameValue; } } protected override void OnControlAdded(ControlEventArgs e) { base.OnControlAdded(e); var radioButton = e.Control as RadioButton; if (radioButton != null) radioButton.CheckedChanged += radioButton_CheckedChanged; } void radioButton_CheckedChanged(object sender, EventArgs e) { _selected = CheckedRadioButtonIndexPos; SelectedChanged(this, new EventArgs()); } }


Me gustaría hacer una observación sobre el bloque de código que podría ser útil para las personas que leen estas publicaciones. El siguiente código puede no funcionar siempre como se esperaba debido a su estructura.

try { val = System.Enum.Parse(this.enumType, rb.Text) as System.Enum; } catch(Exception ex) { // cannot occurred if code is safe System.Windows.Forms.MessageBox.Show("No enum value for this radio button : " + ex.ToString()); } object obj = this.bindingSource.Current; obj.GetType().GetProperty(propertyName).SetValue(obj, val, new object[] { } ); this.bindingSource.CurrencyManager.Refresh();

Si se produce un error en el bloque try, se ejecutará el bloque catch. El código continuará ejecutándose después del bloque catch. Dado que no se manejaba la fuente de enlace, las variables que siguen a la captura podrían terminar en un estado indeterminado y pueden arrojar otra excepción que puede o no ser manejada.

Un mejor enfoque es el siguiente

try { val = System.Enum.Parse(this.enumType, rb.Text) as System.Enum; object obj = this.bindingSource.Current; obj.GetType().GetProperty(propertyName).SetValue(obj, val, new object[] { }); this.bindingSource.CurrencyManager.Refresh(); } catch(EntityException ex) { // handle error } catch(Exception ex) { // cannot occurred if code is safe System.Windows.Forms.MessageBox.Show("No enum value for this radio button : " + ex.ToString()); }

Esto permite manejar el error de valor de enum así como otros errores que puedan ocurrir. Sin embargo, utilice la EntityException o variaciones de la misma antes del bloque Exception (todas las versiones de Exception tienen que aparecer primero). Uno puede obtener información específica del estado de la entidad para un error del marco de la entidad al usar las clases del marco de la entidad en lugar de la clase base de la Excepción. Esto puede ser útil para depurar o proporcionar mensajes de tiempo de ejecución más claros para el usuario.

Cuando configuro bloques try-catch me gusta verlo como una "capa" en la parte superior del código. Tomo decisiones sobre el flujo de las excepciones a lo largo del programa, su visualización para el usuario y cualquier limpieza que se requiera para permitir que el programa continúe funcionando correctamente sin objetos en un estado indeterminado que pueda conectarse en cascada a otros errores.


Mi enfoque es colocar cada botón de radio en su propio panel antes de vincularlos a una propiedad booleana:

public static Binding Bind<TObject>(this RadioButton control, object dataSource, string dataMember) { // Put the radio button into its own panel Panel panel = new Panel(); control.Parent.Controls.Add(panel); panel.Location = control.Location; panel.Size = control.Size; panel.Controls.Add(control); control.Location = new Point(0, 0); // Do the actual data binding return control.DataBindings.Add("Checked", dataSource, dataMember); }


Sé que esta publicación es antigua, pero en mi búsqueda de una respuesta para este mismo problema encontré esta publicación y no resolvió mi problema. Terminé haciendo estallar una bombilla al azar hace un minuto y quería compartir mi solución.

Tengo tres botones de radio en un cuadro de grupo. Estoy usando una Lista <> de un objeto de clase personalizado como fuente de datos.

Objeto de clase:

using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace BAL { class ProductItem { // Global Variable to store the value of which radio button should be checked private int glbTaxStatus; // Public variable to set initial value passed from // database query and get value to save to database public int TaxStatus { get { return glbTaxStatus; } set { glbTaxStatus = value; } } // Get/Set for 1st Radio button public bool Resale { // If the Global Variable = 1 return true, else return false get { if (glbTaxStatus.Equals(1)) { return true; } else { return false; } } // If the value being passed in = 1 set the Global Variable = 1, else do nothing set { if (value.Equals(true)) { glbTaxStatus = 1; } } } // Get/Set for 2nd Radio button public bool NeverTax { // If the Global Variable = 2 return true, else return false get { if (glbTaxStatus.Equals(2)) { return true; } else { return false; } } // If the value being passed in = 2 set the Global Variable = 2, else do nothing set { if (value.Equals(true)) { glbTaxStatus = 2; } } } // Get/Set for 3rd Radio button public bool AlwaysTax { // If the Global Variable = 3 return true, else return false get { if (glbTaxStatus.Equals(3)) { return true; } else { return false; } } // If the value being passed in = 3 set the Global Variable = 3, else do nothing set { if (value.Equals(true)) { glbTaxStatus = 3; } } } // More code ...

Tres variables públicas separadas con get / set accediendo a la misma variable global.

En el código subyacente, tengo una función llamada durante la configuración Page_Load () que establece todos los controles de enlace de datos. Para cada botón de radio, agrego su propio control de datos.

radResale.DataBindings.Add("Checked", glbProductList, "Resale", true, DataSourceUpdateMode.OnPropertyChanged, false); radNeverTax.DataBindings.Add("Checked", glbProductList, "NeverTax", true, DataSourceUpdateMode.OnPropertyChanged, false); radAlwaysTax.DataBindings.Add("Checked", glbProductList, "Always", true, DataSourceUpdateMode.OnPropertyChanged, false);

¡¡Espero que esto ayude a alguien!!