[WPF] binding probleem combobox

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • -Rombo-
  • Registratie: April 2002
  • Laatst online: 10-09 13:31
Beste Tweakers,

Ik ben bezig met WPF te leren, dit begint me al aardig te lukken maar ik zit al enkele uren vast om een combobox correct gebind te krijgen met de datacontext maar dit wil maar niet lukken.

Ik heb al zitten googlen & het forum doorzocht maar ik kan geen antwoord vinden.

Ik heb een simpel demo applicatie gemaakt om het probleem te illustreren

Afbeeldingslocatie: http://dl.dropbox.com/u/25725851/testcomboboxbinding.png

Dit is gewoon een simpel window met hierop 2 usercontrols.
- usercontrol met hierop de datagrid
- usercontrol met hierop de tekstvelden/combobox

In het window vul ik 2 observable collections op:
- 'NotebookEntries' en een NotebookEntry bevat een Id, Titel, CategoryId
- 'NotebookCategoryEntries' en een NotebookCategoryEntry bevat: Id, Naam

Ik krijg (zoals ge op de screenshot kunt zien) de titel en het category perfect opgevuld en als ik een andere regel selecteer in de datagrid volgen de gegevens.

Echter de combobox wil maar niet werken.
Ik heb al met SelectedItem en SelectedValue zitten proberen, hierbij ook verschillende Path's, verschillende binding modes, .. maar ik kan de juiste combinatie dus niet vinden.

Wat wil ik dus bereiken:
- regel selecteren in de datagrid dat de combobox de juiste category gaat weergeven
- selecteer ik een andere category in de combobox dat de datagrid geupdate gaat worden

Hier de link naar de demo applicatie, gaat waarschijnlijk gemakkelijker zijn voor jullie om de oplossing te vinden dan dat ik hier 10-tallen stukken code zit te tonen.
(demo app is gemaakt in VS C# 2010 express)

*snip*

Alvast bedankt

[ Voor 1% gewijzigd door Creepy op 26-07-2011 15:40 ]


Acties:
  • 0 Henk 'm!

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 00:12

Creepy

Tactical Espionage Splatterer

Post toch maar de relevante (dus niet alle!) code. Dan blijft dit topic ook nog bruikbaar als jij besluit de zip weg te halen, en stiekum dwingt hert je je probleem uit te kleden tot een klein stukje om het te reproduceren ;) Het is niet de bedoeling dat wij moeten gaan bughunten in je code, dat moet je toch echt eerst zelf proberen.

Dus wat heb je nu al allemaal geprobeerd en wat werkt er nu precies niet dan? Post dan de relevante code. Dan kunnen wij al zien wat je hebt geprobeerd en kunnen we je veel beter van advies te voorzien omdat we al weten wat er niet gaat werken en gaan we ook geen dingen noemen die jij al hebt geprobeerd.

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


Acties:
  • 0 Henk 'm!

  • -Rombo-
  • Registratie: April 2002
  • Laatst online: 10-09 13:31
Ok, geen probleem :)

Het main window met de user controls
C#:
1
2
3
4
<DockPanel Name="dpData">
<custom:NotebookData DockPanel.Dock="Right" x:Name="nbData"></custom:NotebookData>
<custom:NotebookGrid x:Name="nbGrid"></custom:NotebookGrid>
</DockPanel>


De achterliggende code
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
        private NotebookEntries _nbEntries = new NotebookEntries();
        private NotebookCategoryEntries _nbcEntries = new NotebookCategoryEntries();

        public MainWindow()
        {
            InitializeComponent();

            _nbEntries.Add(new NotebookEntry(1, "Entry 1", 3));
            _nbEntries.Add(new NotebookEntry(2, "Entry 2", 1));
            _nbEntries.Add(new NotebookEntry(3, "Entry 3", 2));
            _nbEntries.Add(new NotebookEntry(4, "Entry 4", 1));
            _nbEntries.Add(new NotebookEntry(5, "Entry 5", 3));
            _nbEntries.Add(new NotebookEntry(6, "Entry 6", 2));

            _nbcEntries.Add(new NotebookCategoryEntry(1, "Category 1"));
            _nbcEntries.Add(new NotebookCategoryEntry(2, "Category 2"));
            _nbcEntries.Add(new NotebookCategoryEntry(3, "Category 3"));

// ==> datacontext zet ik op het dockpanel, de datagrid en de velden kunnen hier beiden dan aan
            dpData.DataContext = _nbEntries;

// ==> ik zet hier de datacontext op de combobox
            nbData.cbCategory.DataContext = _nbcEntries;
        }


De usercontrol met de datagrid
C#:
1
<DataGrid Name="dgNotebook" ItemsSource="{Binding}" IsSynchronizedWithCurrentItem="True" ></DataGrid>


De usercontrol met de velden
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
        <TextBlock Grid.Column="0" Grid.Row="0">Titel</TextBlock>
        <TextBox Grid.Column="1" Grid.Row="0" Text="{Binding Path=Title, Mode=TwoWay}"></TextBox>

        <TextBlock Grid.Column="0" Grid.Row="1">Category ID</TextBlock>
        <TextBox Grid.Column="1" Grid.Row="1" Text="{Binding Path=CatId, Mode=TwoWay}"></TextBox>

        <TextBlock Grid.Column="0" Grid.Row="2">Category Combo</TextBlock>
        <ComboBox Grid.Column="1" Grid.Row="2" Name="cbCategory" 
                  ItemsSource="{Binding}"
                  DisplayMemberPath="CatName"
                  SelectedValuePath="CatUid"
                  IsSynchronizedWithCurrentItem="True"
                  SelectedValue="{Binding ElementName=dpData, Path=NotebookEntry, Mode=TwoWay}"
                  >
            <!--    
==> één van de andere testen      
              SelectedValue="{Binding ElementName=dpData, Path=CatId, Mode=TwoWay}"
            -->
        </ComboBox>


Verschillende classes om de data bij te houden
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
    public class NotebookEntry
    {
        private int _id;
        private string _title;
        private int _catId;

        public NotebookEntry(int id, string title, int catId)
        {
            _id = id;
            _title = title;
            _catId = catId;
        }
       
        public int Id
        {
            get { return _id; }
            set { _id = value; }
        }
        public string Title
        {
            get { return _title; }
            set { _title = value; }
        }
        public int CatId
        {
            get { return _catId; }
            set { _catId = value; }
        }
    }

    public class NotebookCategoryEntry
    {
        private int _catUid;
        private string _catName;

        public NotebookCategoryEntry(int catUid, string catName)
        {
            _catUid = catUid;
            _catName = catName;
        }

        public int CatUid
        {
            get { return _catUid; }
            set { _catUid = value; }
        }
        public string CatName
        {
            get { return _catName; }
            set { _catName = value; }
        }
    }

   public class NotebookEntries : ObservableCollection<NotebookEntry>
    {
    }

    public class NotebookCategoryEntries : ObservableCollection<NotebookCategoryEntry>
    {
    }

Acties:
  • 0 Henk 'm!

  • Rikkos
  • Registratie: November 2010
  • Laatst online: 06-03 06:59
Je zit wel in de goede richting.

Je komt in eerste instantie helemaal niet bij de datagrid van de nbGrid usercontrol, dit maakt het ook moeilijker omdat je 2 verschillende usercontrols maakt. Ik zou het simpel houden en gewoon alles in 1 doen.

Nu als volgt. je datagrid zit voor zover ik zie in dpData.nbGrid.dgNotebook. Als je dat zou kunnen bereiken in code-behind (gewoon om te kijken of je er bij kan) dan zou je de volgende binding moeten kunnen doen. {Binding ElementName=dpData, Path=nbGrid.dgNotebook.SelectedItem.CatId, Mode=TwoWay}

Ik hoop dat ik je in de goede richting heb gestuurd.

[ Voor 194% gewijzigd door Rikkos op 27-07-2011 10:01 ]


Acties:
  • 0 Henk 'm!

  • -Rombo-
  • Registratie: April 2002
  • Laatst online: 10-09 13:31
Is me niet gelukt

Gaat WPF eigenlijk intern zelf casten?
{Binding ElementName=dpData, Path=nbGrid.dgNotebook.SelectedItem.CatId, Mode=TwoWay}

SelectedItem.CatId gaat toch maar enkel als SelectedItem een NotebookEntry is (en dat is het ook wel maar niet zolang dat niet gecast is?)

Ik heb het volgende eens zitten proberen:
In de NotebookData usercontrol een property in voorzien om de DataGrid in bij te houden en die property zet ik even vanuit mijn MainWindow. Zeker geen propere code maar dan kan ik het volgende wel realiseren:

C#:
1
2
3
4
5
6
7
8
9
10
11
12
        private void btnTest_Click(object sender, RoutedEventArgs e)
        {
            NotebookEntry ne = DG.SelectedItem as NotebookEntry;
            cbCategory.SelectedValue = ne.CatId;
        }

        private DataGrid _dg;
        public DataGrid DG
        {
            get { return _dg; }
            set { _dg = value; }
        }


En als ik dan op die button click wordt perfect de juiste waarde in de combobox geselecteerd, maar dus zonder binding :(

Update:

ik heb de usercontrols eens wegglaten en alles dus gewoon in het window gestoken en dan krijg ik het wel perfect werkende:

SelectedValue="{Binding ElementName=dgNotebook, Path=SelectedItem.CatId, Mode=TwoWay}"

Dus dan zal ik het wat anders gaan moeten oplossen maar heb ik de binding dus toch al werkende, bedankt !

[ Voor 13% gewijzigd door -Rombo- op 27-07-2011 11:36 ]


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
C#:
1
2
3
4
5
6
<ComboBox Grid.Column="1" Grid.Row="2" Name="cbCategory"  
                  ItemsSource="{Binding}" 
                  DisplayMemberPath="CatName" 
                  SelectedValuePath="CatUid" 
                  IsSynchronizedWithCurrentItem="True" 
                  SelectedValue="{Binding ElementName=dpData, Path=NotebookEntry, Mode=TwoWay}">

Je SelectedValue en ItemsSource kloppen hier zo te zien niet. Je ItemsSource moet verwijzen naar je NotebookCategoryEntries, en de SelectedValue binding klopt ook niet, die zal moeten verwijzen naar de huidige category van het SelectedItem van je dgNotebook datagrid.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”

Pagina: 1