Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Binding WinForms control to ObjectA.ObjectB.Property

I have a class that represents a car like this:

public class Car
{
    public event PropertyChangedEventHandler PropertyChanged;

    private void RaisePropertyChanged([CallerMemberName] string caller = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(caller));
        }
    }

    public enum Colors
    {
        LaserRed,
        GenuineGraniteMica,
        BluePearl,
        SandMicaMetallic,
        NightArmorMetallic
    }

    private string _make;
    public string Make
    {
        get { return _make; }
        set {
                _make = value;
                RaisePropertyChanged();
            }
    }

    private string _model;
    public string Model
    {
        get { return _model; }
        set {
                _model = value;
                RaisePropertyChanged();
            }
    }

    private Colors _color;
    public Colors Color
    {
        get { return _color; }
        set {
                _color = value;
                RaisePropertyChanged();
            }
    }

    public Tire FrontLeftTire = new Tire();
    public Tire FrontRightTire = new Tire();
    public Tire RearLeftTire = new Tire();
    public Tire RearRightTire = new Tire();

    public Car()
    {
        // initialization code
    }

As you can see, my Car class has four tires and the Tire class looks like this:

public class Tire : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private void RaisePropertyChanged([CallerMemberName] string caller = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(caller));
        }
    }

    public enum SizeValues
    {
        [Description("17 inches")]
        SeventeenInches,
        [Description("18 inches")]
        EighteenInches,
        [Description("19 inches")]
        NineteenInches,
        [Description("20 inches")]
        TwentyInches,
    }

    private string _brand;
    public string Brand
    {
        get { return _brand; }
        set
        {
            _brand = value;
            RaisePropertyChanged();
        }
    }

    private SizeValues _size;
    public SizeValues Size
    {
        get { return _size; }
        set
        {
            _size = value;
            RaisePropertyChanged();
        }
    }

    public Tire()
    {
        // initialization code
    }

In my WinForms UI, I have a combobox (dropdownlist) that corresponds to the Size property of each tire. I'm trying to bind each combobox to the appropriate tire's Size property but the code I've been using to bind to properties of the car object itself isn't working. Here's the code that I use to bind a combobox to the Color property of my car:

comboBoxCarColor.DataBindings.Add(new Binding("SelectedValue", bindingSourceForCars, "Color", true, DataSourceUpdateMode.OnPropertyChanged));
comboBoxCarColor.DataSource = new BindingSource(Utility.ConvertEnumToListOfKeyValuePairs(typeof(Car.Color)), null);
comboBoxCarColor.DisplayMember = "Value";
comboBoxCarColor.ValueMember = "Key";

This works fine. But I think the problem that I'm running into now is that I'm trying to bind to a property that is not a direct child property of the car but rather a property of one of the car's tires. So, something like this isn't working:

comboBoxFrontLeftTimeSize.DataBindings.Add(new Binding("SelectedValue", bindingSourceForCars, "FrontLeftTire.Size", true, DataSourceUpdateMode.OnPropertyChanged));

I think the problem is with the data member ("FrontLeftTire.Size") but I'm not certain. Am I just referencing this the wrong way or am I completely mistaken in my approach here?

like image 289
bmt22033 Avatar asked Jan 30 '13 15:01

bmt22033


1 Answers

I think there are two issues:

1) I think you need to declare your Tire objects as Properties, not Fields:

Instead of this:

public Tire FrontLeftTire = new Tire()

Try changing it to:

private Tire frontLeftTire = new Tire()

public Tire FrontLeftTire {
  get { return frontLeftTire; }
}

2) I think you might be hitting a breaking change that Microsoft made in 4.0 regarding data members that requires using a BindingSource.

Instead of this:

comboBoxFrontLeftTimeSize.DataBindings.Add(
                            new Binding("SelectedValue",
                                        bindingSourceForCars,
                                        "FrontLeftTire.Size",
                                        true,
                                        DataSourceUpdateMode.OnPropertyChanged));

Try changing it to:

BindingSource bs = new BindingSource(bindingSourceForCars, null);
comboBoxFrontLeftTimeSize.DataBindings.Add(
                                       "SelectedValue",
                                       bs,
                                       "FrontLeftTire.Size",
                                       true,
                                       DataSourceUpdateMode.OnPropertyChanged));
like image 57
LarsTech Avatar answered Sep 29 '22 05:09

LarsTech