I need to bind a GroupBox
to a BindingSource
, which in turn is bound to the following object:
public class CustomerType
{
public int Id {get; set;}
public string Name {get; set;}
public MemberType MemberType {get; set;}
}
public enum MemberType {Adult, Child}
I followed this answer to create a custom GroupBox. I also set the data bindings as follows:
groupBoxMemberType.DataBindings.Add("Selected", this.bindingSource, "MemberType");
However, when loading an existing object, I get the following exception:
DataBinding cannot find a row in the list that is suitable for all bindings.
The exception occurs when setting the data source:
customerType = customerTypeRequest.Load(id);
bindingSource.DataSource = customerType; //raises exception
What am I missing? Is there an alternative to get radio buttons to bind to a datasource, specifically a BindingSource
?
This is the changed code:
[DefaultBindingProperty("Selected")]
public class RadioGroupBox : GroupBox
{
#region events
[Description("Occurs when the selected value changes.")]
public event SelectedChangedEventHandler SelectedChanged;
public class SelectedChangedEventArgs : EventArgs
{
public int Selected { get; private set; }
internal SelectedChangedEventArgs(int selected)
{
this.Selected = selected;
}
}
public delegate void SelectedChangedEventHandler(object sender, SelectedChangedEventArgs e);
#endregion
private int selected;
[Browsable(false)]
[Bindable(BindableSupport.Yes, BindingDirection.TwoWay)]
[Description("The selected value associated with this control."), Category("Data")]
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;
}
protected void OnSelectedChanged(SelectedChangedEventArgs e)
{
if (SelectedChanged != null)
SelectedChanged(this, e);
}
private 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;
OnSelectedChanged(new SelectedChangedEventArgs(selected));
}
}
}
Further to setting the Tag
property to the corresponding int value of the enum, you need to subscribe to the SelectedChanged event in your form, eg:
private void radioGroupBoxMemberType_SelectedChanged(object sender, SelectedChangedEventArgs e)
{
customerType.MemberType = (MemberType)e.Selected;
}
Improvements to this class would be:
Inherit from RadioButton and use a new property instead of the Tag
property.
Access and set the bindingsource property directly in the control to avoid subscribing to the event.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With