[C#] BindingSource en DataGridViewComboBox

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Tony L
  • Registratie: September 2005
  • Laatst online: 07-11-2015
Ik zit al een paar dagen te vechten met een raar probleem waar ik maar niet uitkom. Het komt er op neer dat de values van de BindingSource niet geupdate worden.

Requirement van mijn voorbeeld:
- Form met een DataGridView
- Een class "Car" (zie onder).

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    public class Car {
        private int id;
        private string name;

        public int ID {
            get { return id; }
            set { id = value; }
        }

        public string Name {
            get { return name; }
            set { name = value; }
        }

        public Car CurrentInstance {
            get { return this; }
        }
    }


De reden dat ik er een "CurrentInstance" property in heb gezet heeft te maken met het eenvoudig uitkunnen lezen van de waarde in de DataGridView.

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
    public partial class formTest : Form {
        DataGridViewComboBoxColumn column = new DataGridViewComboBoxColumn();
        IList<Car> dataGridDataSource = new List<Car>();

        public formTest() {
            InitializeComponent();
        }

        private void formTest_Load(object sender, EventArgs e) {

            column.DisplayMember = "Name";
            column.ValueMember = "CurrentInstance";
            column.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
            column.DataSource = createBindingSource();
            dataGridView.Columns.Add(column);
            
            bindingSource.DataSource = dataGridDataSource;
        }

        private BindingSource createBindingSource() {
            Car item1 = new Car();
            item1.ID = 1;
            item1.Name = "Car 1";

            Car item2 = new Car();
            item2.ID = 2;
            item2.Name = "Car 2";

            Car item3 = new Car();
            item3.ID = 3;
            item3.Name = "Car 3";

            IList<Car> itemList = new List<Car>();
            itemList.Add(item1);
            itemList.Add(item2);
            itemList.Add(item3);

            BindingSource bindingSource = new BindingSource();
            bindingSource.DataSource = itemList;
            return bindingSource;
        }
    }
}


Ik voeg op runtime als gebruiker wat waarden toe en ik zie dat het grid gevuld wordt. In dit geval voeg ik 2 waardes toe, "Car 2" en "Car 3". Als ik nu break en kijk wat de waarden in de DataGridView zijn dan krijg ik er de volgende waarden uit:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
?dataGridView[0, 0].Value
{MBMS.GUI.Forms.Car}
    CurrentInstance: {MBMS.GUI.Forms.Car}
    ID: 2
    id: 2
    Name: "Car 2"
    name: "Car 2"
?dataGridView[0, 1].Value
{MBMS.GUI.Forms.Car}
    CurrentInstance: {MBMS.GUI.Forms.Car}
    ID: 3
    id: 3
    Name: "Car 3"
    name: "Car 3"


Zover lijkt het dus allemaal te kloppen! Alleen als ik dan de BindingSource bekijk dan ziet het resultaat er zo uit:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
?bindingSource[0]
{MBMS.GUI.Forms.Car}
    CurrentInstance: {MBMS.GUI.Forms.Car}
    ID: 0
    id: 0
    Name: null
    name: null
?bindingSource[1]
{MBMS.GUI.Forms.Car}
    CurrentInstance: {MBMS.GUI.Forms.Car}
    ID: 0
    id: 0
    Name: null
    name: null


Er zitten er dus wel 2 in maar van de waardes klopt helemaal niets. Alsof er twee nieuwe instanties zijn aangemaakt maar de waardes van de DataGridView vervolgens niet zijn gekoppeld op het moment dat de keuze is gemaakt. Ik begrijp er niets van want die 2 moeten 1-op-1 gelinked zijn toch?? Ik moet wat over het hoofd zien...

Ik hoop dat iemand mij verder op weg kan helpen!

PSN: Norfirin


Acties:
  • 0 Henk 'm!

  • marco_balk
  • Registratie: April 2001
  • Laatst online: 20-06 21:52
Wellicht moet je eens kijken naar een BindingList<T> ipv een IList<T>.
Zie http://msdn.microsoft.com...y/ms158145(v=VS.100).aspx

Acties:
  • 0 Henk 'm!

  • Spiral
  • Registratie: December 2005
  • Niet online
Voor een bi-directionele binding, moet je op je Car object de INotifyPropertyChanged interface implementeren

To say of what is that it is not, or of what is not that it is, is false, while to say of what is that it is, and of what is not that it is not, is true. | Aristoteles


Acties:
  • 0 Henk 'm!

  • Tony L
  • Registratie: September 2005
  • Laatst online: 07-11-2015
marco_balk schreef op maandag 31 mei 2010 @ 10:41:
Wellicht moet je eens kijken naar een BindingList<T> ipv een IList<T>.
Zie http://msdn.microsoft.com...y/ms158145(v=VS.100).aspx
Ik heb net je suggestie geprobeerd maar dit werkt helaas ook niet (zelfde probleem als wat ik hierboven heb geschreven).
Spiral schreef op maandag 31 mei 2010 @ 11:04:
Voor een bi-directionele binding, moet je op je Car object de INotifyPropertyChanged interface implementeren
Dit is toch alleen van invloed op het moment dat ik een object wijzig BUITEN de grid waardoor deze direct wordt geupdate IN de grid? Ik heb het iig geimplementeerd maar het werkt helaas niet (weer hetzelfde probleem).


Ik heb veel voorbeelden van de DataGridViewComboBoxColumn gezien maar de case is altijd anders dan wat ik hierboven probeer te doen.

Voorbeeld:
- Een auto heeft een enumeratie CarType { Cabrio, Normaal }
- In de DataGridView heb je 2 kolommen, Naam en CarType (die overeenkomen met de properties in de Car class.

Dit werkt maar dit is totaal anders dan wat ik probeer te doen.

Voorbeeld:
- Ik heb een CarDealer met een property "Cars" van het type IList<T>.
- In de DataGridView wil ik bestaande auto's toevoegen aan een dealer d.m.v. de ComboBox. De ComboBox bevat dus alle auto's die beschikbaar zijn en die gekoppeld kunnen worden aan de CarDealer.

Het verschil in het 1e voorbeeld is dat dit op Property niveau werkt waarbij alles 1-op-1 gemapped kan worden. In het laatste voorbeeld is dit niet het geval omdat ik de geselecteerde objecten wil toevoegen aan de IList<T> collectie van de CarDealer. Ik vraag me af of dit überhaupt wel gaat werken.

Misschien handig om te vermelden dat de bovenstaande case slechts een test-case is. Als dit werkt kan ik namelijk weer verder met het project waar ik mee bezig was :)

PSN: Norfirin


Acties:
  • 0 Henk 'm!

  • Tony L
  • Registratie: September 2005
  • Laatst online: 07-11-2015
Ik heb wat nieuws geprobeerd. Ik heb op het Car object IEditableObject geimplementeerd.

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
        private bool editMode = false;

        private int id;
        private int _id;
        private string name;
        private string _name;

        public void BeginEdit() {
            if (!editMode) {
                _id = id;
                _name = name;
            }
            editMode = true;
        }

        // Rest is achterwege gelaten


De ID en Name properties zijn nog steeds 0 en NULL. Als ik dan het volgende doe:

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
        private bool editMode = false;

        private int id;
        private int _id;
        private string name;
        private string _name;

        public void BeginEdit() {
            if (!editMode) {
                id = 100;
                name = "BeginEdit";
            }
            editMode = true;
        }

        // Rest is achterwege gelaten


Dan zie ik dat het object wat ik kies van naam veranderd en in de BindingSource[0] komt ook 100 en "BeginEdit" terug. Erg logisch allemaal alleen ik begrijp nog steeds niet waarom het object nooit geset wordt. Op 1 of andere manier krijgen de gekoppelde objecten in de IList<T> nooit de oorspronkelijke waardes toegewezen?

Het lijkt me stug dat ik de enige ben met dit probleem? :/

PSN: Norfirin


Acties:
  • 0 Henk 'm!

  • Phyxion
  • Registratie: April 2004
  • Niet online

Phyxion

_/-\o_

Wat doe je nou precies met dataGridDataSource want deze wordt nergens geset verder behalve geinitialized?

Wil je niet gewoon van het grid de bindingsource zetten?

'You like a gay cowboy and you look like a gay terrorist.' - James May


Acties:
  • 0 Henk 'm!

  • Tony L
  • Registratie: September 2005
  • Laatst online: 07-11-2015
Phyxion schreef op dinsdag 01 juni 2010 @ 22:32:
Wat doe je nou precies met dataGridDataSource want deze wordt nergens geset verder behalve geinitialized?

Wil je niet gewoon van het grid de bindingsource zetten?
Wat ik heb gedaan wat hier niet zo goed zichtbaar is:
- Ik heb een BindingSource op het Form gesleept
- De DataGridView heb ik gekoppeld aan deze BindingSource
- Vervolgens koppel ik de dataGridDataSource aan de BindingSource.DataSource (regel 17)

De dataGridDataSource moet uiteindelijk alle gekozen objecten bevatten die ik aan de DataGridView heb toegevoegd middels de DataGridViewComboBoxColumn. Dat hij dus slechts geinitalizeerd is klopt omdat er bij het opstarten van het Form nog niets gekozen is. Ik zie ook dat als ik een keuze heb gemaakt dat er een nieuw object wordt toegevoegd aan de dataGridDataSource. Alleen zijn dit dan niet de geselecteerde keuzes maar nieuw geinitializeerde objecten van het type Car. Vandaar dat de ID's altijd op 0 staan en de Name altijd op NULL.

Als ik bij het initializeren van het Form een nieuw object toevoeg van het type Car aan de dataGridDataSource (bv. ID=1, Name="Car 1") dan komt deze gewoon netjes in het DataGridView terecht.

PSN: Norfirin

Pagina: 1