Announcement

Collapse
No announcement yet.

Problem mit DataGridViewComboBoxColumn

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Problem mit DataGridViewComboBoxColumn

    Hallo, ich habe ein großes Problem mit Comboboxen in meinem DataGridView.
    Ich bekomm einfach keine Daten da rein.

    Das Grid kommt in der Applikation zig mal vor, immer anders. D.h. es ist eine Klasse MyGrid definiert, die sich von DataGridView ableitet. Das aber auch erst seit knapp 1 Woche. Vorher (das Programm ist noch aus VB6 Zeiten) leitete es sich von DataGrid ab und ich bin dabei das ganze auf .net 2.0 umzustellen.

    Mit dem DataGrid wurden die Tabellen über TableStyles definiert und irgendwo im Code (fragt mich nicht wo, ein Teller Spagetthi ist geordneter) passiert das immernoch. Von diesen Styles muss ich nun die Spalten des Grids ableiten. Bei normalen TextBoxColumns und CheckBoxColumns (vorher BooleanColumn) funktioniert das auch astrein. Aber mit den ComboBoxColumns renn ich momentan gegen Betonwände.


    Hier mal mein Code für die Übernahme aus den TableStyles. Vielleicht sieht ja jemand, was ich falsch mache, oder anders machen muss:
    Code:
        Public Sub TableStyleAdd(ByVal value As DataGridTableStyle)
            MyTableStyle = value
            Dim ind As Integer = 0
            Dim zusatz As Integer = 0 '## wenn Zusatzliche Spalte dann den Zähler ein Hoch
            For Each gcs As DataGridColumnStyle In MyTableStyle.GridColumnStyles
                'Dim test As String = Me.MyTableStyle.GridColumnStyles(ind).GetType.Name
                Select Case Me.MyTableStyle.GridColumnStyles(ind).GetType.Name
                    Case "CC_DataGridBoolColumn"
                        Dim checkCol As New DataGridViewCheckBoxColumn
                        checkCol.Name = gcs.MappingName
                        checkCol.HeaderText = gcs.HeaderText
                        Me.Columns.Add(checkCol)
                    Case "CC_DataGridComboBoxColumnStyle"
                        Dim comboCol As New DataGridViewComboBoxColumn
                        comboCol.Name = gcs.MappingName
                        comboCol.HeaderText = gcs.HeaderText
                        comboCol.DisplayMember = gcs.MappingName & "_$ID" 
    
                        '## zusätzliche Spalte anlegen 
                        Dim textCol As New DataGridViewTextBoxColumn
                        textCol.Name = gcs.MappingName & "_$ID"
                        textCol.HeaderText = ""
                        textCol.Visible = False
                        textCol.DataPropertyName = gcs.MappingName
                        zusatz += 1
    
                        Me.Columns.Add(comboCol)
                        Me.Columns.Add(textCol)
    
                    Case Else
                        Me.Columns.Add(gcs.MappingName, gcs.HeaderText)
                End Select
    
    
    
    
                Dim col As DataGridViewColumn = Me.Columns(ind + zusatz)
                col.Width = gcs.Width
                col.ReadOnly = gcs.ReadOnly
                col.DataPropertyName = gcs.MappingName
                If col.Width <= 5 Then
                    col.Visible = False
                End If
                ind += 1
            Next
            Me.RowHeadersVisible = MyTableStyle.RowHeadersVisible
            Me.RowHeadersWidth = MyTableStyle.RowHeaderWidth + 5
            Me.ColumnHeadersVisible = MyTableStyle.ColumnHeadersVisible
            Me.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.DisplayedCells
            Me.AllowUserToAddRows = Me.RowHeadersVisible
    
        End Sub

    EDIT: Noch zur Erklärung. Sämtliche Formulare im Programm werden in XML-Dateien definiert. Da drin sind auch das Grid und seine Spalten definiert. Irgendwo wird das ganze dann ausgelesen und daraus diese Table-Styles gebastelt. Diese Stelle hab ich noch nicht identifizieren können.
    Zuletzt editiert von Andreas Mahr; 11.04.2008, 11:17.

  • #2
    Hallo Andreas,

    mit den Styles habe ich mich noch nicht befasst; meine Hinweise liegen deshalb vielleicht völlig falsch. Ich vermisse DataSource und vor allem DataGridViewComboBoxColumn.ValueMember.

    Jürgen

    Comment


    • #3
      Hi Jürgen,

      dein hinweis war Goldrichtig. Ich hab mich ein wenig durchgewühlt und hab tatsächlich properties gefunden, in denen DataSource und DisplayMember für die ComboBoxColumn gehalten werden.
      Hab die jetzt entsprechend in meinen Code eingefügt und zum größten Teil werden die boxen jetzt richtig gefüllt und dargestellt. Da wo dies nicht geschieht muss ich nochmal schaun.

      Comment


      • #4
        Wie kann ich jetzt das Selected_Value oder Index Ereignis der Combobox abfangen? Das Grid selber kennt es nicht und ich sehe keinen Weg daran zu kommen.

        Comment


        • #5
          Hallo Andreas,

          das ist etwas trickreich. Das DataGridView benutzt intern genau eine ComboBox. An diese musst Du herankommen und auswerten. Bei der Auswertung musst Du genau untersuchen, welche Spalte und Zeile und welcher Inhalt gerade verwendet wird, also zusätzlich DGV.CurrentCell prüfen.

          Bereite zunächst eine Auswertung für eine ComboBox vor, etwa so:
          Code:
          //  Entschuldigung, in C# sieht es so aus:
          private void InternalComboBox_SelectedIndexChanged(object sender, 
          		System.EventArgs e)
          {
          	ComboBox comboBox = (ComboBox) sender;
          	//  Inhalte dieser comboBox prüfen
          }
          Das entscheidende Ereignis ist DataGridView.EditingControlShowing. Dies verknüpft die interne ComboBox mit diesem EventHandler:
          Code:
          void DgvEditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
          {
          	if (e.Control is ComboBox) {
          		ComboBox box = e.Control as ComboBox;
          		if (box.SelectedIndexChanged == null)
          			box.SelectedIndexChanged 
          			+= InternalComboBox_SelectedIndexChanged;
          	}
          }
          Ich verstehe allerdings nicht, warum NET die ComboBox mit Ereignissen und Werten nicht direkt zur Verfügung stellt. Vielleicht liegt es daran, dass sowieso vorzugsweise die dahinterliegenden Daten geprüft werden sollen, also z.B. DataTable.RowChanged.

          Gruß Jürgen

          Comment


          • #6
            Hallo Jürgen,

            danke für die Antwort. Ich werd das gleich mal ausprobieren.
            Das Problem an meinem grid ist, das, wenn ich etwas in der Combobox ändere, ich keine DataTable.Row.Changed - Event bekomme. Erst wenn ich in eine andere Zelle was schreibe, kommt das Teil. Hierbei trickst mich dann die Logik, die damals in VB6 in dieses Teil (damals ja noch DataGrid) implementiert wurde, aus, wenn ich eine neue Zeile anlege. Diese wird mit dem Wert aus der ComboBox angelegt und alles andere, was ich schon in die zeile geschrieben habe, wird ignoriert. Wenn ich mehrere Zeilen anlege, wird nur die erste übernommen.
            Es ist echt zum verrückt werden

            Comment


            • #7
              Vielleicht ist in diesem Fall DataTable.RowChanging besser geeignet. (Ich weiß es noch nicht; ich versuche, möglichst ohne Ereignisse auszukommen, und habe deshalb noch nicht alles selbst versucht.) Jürgen

              PS. Das Verfahren mit EditingControlShowing habe ich bei einer ComboBox noch nicht genutzt. Aber bei einer TextBox-Spalte, die automatisch Großbuchstaben eintragen soll, klappt es so.

              Comment


              • #8
                Hmm...Änderungen an der Combobox schlagen in keinem DataTable-Event auf. Hab jetzt 4 oder 5 ausprobiert.

                Ich werds jetzt mal über dieses Combobox.valueChange event probieren, vllt komm ich da ja weiter.

                Als das Programm noch datagrid verwendet hat, hat es scheinbar eine unsichtbare Id-Spalte für die Combobox-Spalte angelegt. Seit der Umstellung auf dataGridView wird dies nicht mehr gemacht (bei machen wiederum schon). In dieser ID-Spalte wurde dann der Wert der Combobox, bzw. die ID des Wertes in der Combobox verwaltet. Ich denke, da haben die Events dann gegriffen.
                Ich hab keinen Schimmer wieso diese Spalte nicht mehr angelegt wird.
                Ich darf dir ja leider den Code nicht zeigen, aber wenn du ihn sehen würdest, du würdest schreiend davon laufen. Ich kann diesen Reflex jeden tag nur mit Mühe unterdrücken

                Comment


                • #9
                  ich hab jetzt mal den C#-Code von oben ins vb.net umgebastelt.
                  Das funktioniert aber nicht wirklich. Ich hab leider keine Ahnung, wie man Events in vb erstellt.
                  Die ROT makierten werden als Fehler angezeigt.


                  Code:
                  Private Sub InternalComboBox_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs)
                  
                          Dim CbBox As ComboBox = CType(sender, ComboBox)
                          '  Inhalte dieser comboBox prüfen
                      End Sub
                  
                      Private Sub CC_DataGrid_EditingControlShowing(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles Me.EditingControlShowing
                          If (e.Control.Name = "ComboBox") Then
                              Dim box As ComboBox = CType(e.Control, ComboBox)
                              If box.SelectedIndexChanged Is Nothing Then
                                  box.SelectedIndexChanged += InternalComboBox_SelectedIndexChanged()
                              End If
                          End If
                  
                      End Sub

                  Comment


                  • #10
                    Originally posted by Andreas Mahr View Post
                    Das funktioniert aber nicht wirklich. Ich hab leider keine Ahnung, wie man Events in vb erstellt.
                    Das weiß ich (natürlich) auch nicht, aber ich habe inzwischen gelesen, dass das mit AddHandler + AddressOf geht.

                    Der Vergleich über "(e.Control.Name = "ComboBox")" ist nicht korrekt: Du darfst nicht den Namen des Controls als Namen des Typs verwenden. Korrekt ist der Vergleich über:
                    Code:
                    If (TypeOf e.Control Is ComboBox) Then ...
                    Jürgen

                    PS. Ich bitte um Entschuldigung, dass ich im Unterforum für VB.NET immer wieder mit C# ankomme. Wenn ich bei einer NET-Frage sinnvoll antworten kann, ist Hilfe mit C# hoffentlich besser als keine Hilfe.
                    Zuletzt editiert von Jürgen Thomas; 16.04.2008, 17:32.

                    Comment


                    • #11
                      ok, ich hab das jetzt soweit auf vb.net umgestrickt

                      Code:
                      Private Event ComboBoxValueChange(ByVal sender As Object, ByVal e As System.EventArgs)
                      
                      Public Sub New()
                              MyBase.New()
                              Me.AutoGenerateColumns = False
                              AddHandler ComboBoxValueChange, AddressOf InternalComboBox_SelectedIndexChanged
                          End Sub
                      
                          Private Sub InternalComboBox_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs)
                      
                              Dim CbBox As ComboBox = CType(sender, ComboBox)
                              '  Inhalte dieser comboBox prüfen
                              MessageBox.Show("tadda")
                          End Sub
                      
                          Private Sub CC_DataGrid_EditingControlShowing(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles Me.EditingControlShowing
                              If (TypeOf e.Control Is ComboBox) Then
                                  Dim box As ComboBox = CType(e.Control, ComboBox)
                                  If box.SelectedIndexChanged Then
                                      RaiseEvent ComboBoxValueChange(e.Control, New System.EventArgs)
                                  End If
                              End If
                      
                          End Sub
                      bei If box.SelectedIndexChanged Then heißt es allerdings, dies sei ein Event und ich darf es so nicht ansprechen.
                      Wenn ich die If-Klausel weglasse, dann funktioniert das auslösen meines Events.
                      Allerdings löst es zu früh aus, nämlich schon, wenn man nur die Combobox anklickt. Nach einer änderung in der Box, wird es nicht ausgelöst.

                      Comment


                      • #12
                        ich habs *jubel*

                        Code:
                            Private Sub InternalComboBox_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs)
                        
                                Dim CbBox As ComboBox = CType(sender, ComboBox)
                                '  Inhalte dieser comboBox prüfen
                                MessageBox.Show("tadda")
                            End Sub
                        
                            Private Sub CC_DataGrid_EditingControlShowing(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles Me.EditingControlShowing
                                If (TypeOf e.Control Is ComboBox) Then
                                    Dim box As ComboBox = CType(e.Control, ComboBox)
                                    If Not box Is Nothing Then
                                        AddHandler box.SelectedIndexChanged, AddressOf InternalComboBox_SelectedIndexChanged
                                    End If
                                End If
                        
                            End Sub
                        man benötigt kein Delegate (so wie ich es vorher probiert hab) da ich ja einfach das vorhandene Umleite auf meinen Handler

                        Comment


                        • #13
                          Ich freue mich mit Dir!

                          Nur noch zwei Anmerkungen:

                          Die Abfrage "If Not box Is Nothing" ist grundsätzlich natürlich wichtig und richtig. In der aktuellen Situation ist dies aber immer wahr wegen der vorherigen Abfrage "If (TypeOf e.Control Is ComboBox)". Ausnahmsweise kann diese Sicherheitsprüfung also entfallen.

                          Bei meinem Code hatte ich eine zusätzliche Prüfung "if (box.SelectedIndexChanged == null)". Dabei ging es mir darum, dass der EventHandler nicht mehrfach zugewiesen werden sollte; denn was passiert, wenn ein spezieller EventHandler schon registriert ist und ein weiteres Mal registriert werden soll? (Diese Situation gibt es in einer DataGridView natürlich mehrfach.) Deshalb habe ich vorsichtshalber diese if-Abfrage vorgenommen.

                          Viel Erfolg weiterhin! Jürgen

                          Comment


                          • #14
                            Originally posted by Jürgen Thomas View Post
                            Bei meinem Code hatte ich eine zusätzliche Prüfung "if (box.SelectedIndexChanged == null)". Dabei ging es mir darum, dass der EventHandler nicht mehrfach zugewiesen werden sollte; denn was passiert, wenn ein spezieller EventHandler schon registriert ist und ein weiteres Mal registriert werden soll? (Diese Situation gibt es in einer DataGridView natürlich mehrfach.) Deshalb habe ich vorsichtshalber diese if-Abfrage vorgenommen.
                            Ja, das habe ich auch gemerkt. Das Problem ist, wie schon erwähnt, das vb scheinbar diese Prüfung als unzulässig ansieht. Ich habe keinen weg gefunden das irgendwie hinzubiegen.
                            Stattdessen geh ich jetzt hin und sage als letzten Befehl im EventHandler
                            Code:
                            RemoveHandler CbBox.SelectedIndexChanged, AddressOf InternalComboBox_SelectedIndexChanged
                            Damit stell ich sicher, das der Handler nur einmal existiert und auch nur dann, wenn er benötigt wird.

                            Danke nochmal für deine Hilfe Jürgen....mal sehn wie weit ich jetzt komme

                            Comment

                            Working...
                            X