none
inserimento di una combobox in una datagridview tramite una comboboxdatagridiviewcell RRS feed

  • Domanda

  • Buongiorno a tutti.

    Non riesco a : data un datagridview allorchè gestisco l'evento "CellBeginEdit" far venire fuori il controllo combobox.

    Sono riuscito a creare e ad aggiungere una colonna di combo chiusi, ma non è quello che voglio, non è quello che si vede di solito fare dai programmi: di solito si vede che clickiamo sulla cella e si apre la combobox.

    E' già da un po' che cerco in internet esempi di codice simile ma inutilmente (mi spiace non essermi potuto arrangiare, ma ormai non so a che santi votarmi).

    Ora il problema se qualcuno può darmi una mano è partire da un pezzo di codice che sia autonomo dal mio progetto ma sia utile alla discussione e dopo tutto quello che ho visto non saprei cosa proporre.

    detto che questo usa la comboboxcolumn e non penso faccia il mio caso (però copiandolo lo potete lanciare subito):

    Public Class Form1

        Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
            Dim combo1 As New DataGridViewComboBoxColumn
            combo1.HeaderText = "Test"
            combo1.Items.AddRange("1", "2", "3", "4")
            DataGridView1.Columns.Add(combo1)
        End Sub
    End Class

    il mio codice (e purtroppo non so renderlo autonomo dal progetto) è questo:

     'Evento generato quando viene visualizzato un controllo per la modifica di una cella
        Private Sub dgvListato_EditingControlShowing(ByVal sender As System.Object,

    ByVal e As             

                                                                                  System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles 

                                                                                                             dgvListato.EditingControlShowing
            Dim cbMotori_datagridview_cell As New DataGridViewComboBoxCell
            cbMotori_datagridview_cell.Items.AddRange("BASE", "ARM1", "ARM2", "WRST", "CLAW")

            Dim X_Origine_Cella As Integer = dgvListato.CurrentCellAddress.X
            Dim Y_Origine_Cella As Integer = dgvListato.CurrentCellAddress.Y
            Dim Origine_cella As New Point(X_Origine_Cella, Y_Origine_Cella)

            ' voglio aggiungere cbMotori_datagridview_cell con origine nella cella e con la larghezza della cella: si può? come?    

           '...  ho provato un sacco di strade ma a tentoni...qualcuno perfavore mi può dare la dritta giusta :-)
        End Sub

    mercoledì 29 luglio 2015 14:32

Risposte

  • Spero di aver ben capito la problematica: in sostanza, mantenere una cella come di semplice testo, ma poi - entrando in essa - poter scegliere da una tendina.

    Ti propongo una soluzione che faccia comparire un ComboBox nella posizione della cella corrente, e che - tramite handler - possa compilare il valore della cella stessa.

    Credo di aver commentato il codice a sufficienza: nel dubbio fammi sapere

        Dim combo As ComboBox   ' ComboBox non ancora valorizzato
    
        ' ...In ingresso della cella
        Private Sub DataGridView1_CellEnter(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellEnter
    
            ' Se la colonna è la seconda (indice 0), ci interessa applicare il combo
            If e.ColumnIndex = 1 Then
    
                ' Istanziamo il ComboBox, e gli assegniamo gli elementi voluti
                combo = New ComboBox()
                Dim items() As String = {"BASE", "ARM1", "ARM2", "WRST", "CLAW"}
                combo.Items.AddRange(items)
    
                ' Calcoliamo il rettangolo che rappresenta lo spazio della cella attuale, ed assegnamo al combo
                ' la Location e la Size corrispondenti, in modo che occupi l'intera cella
                Dim r As Rectangle = DataGridView1.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, True)
                combo.Location = New Point(r.X, r.Y)
                combo.Size = New Size(r.Width, r.Height)
    
                ' Aggiungiamo un handler per fare in modo di controllare la selezione sul combo
                AddHandler combo.SelectedIndexChanged, AddressOf SelezioneCombo
    
                ' L'eventuale valore di cella deve essere trasferito come testo del combo
                combo.SelectedItem = DataGridView1.CurrentCell.Value
    
                ' Aggiungiamo il combo alla griglia
                DataGridView1.Controls.Add(combo)
            End If
        End Sub
    
        ' ... in uscita dalla cella
        Private Sub DataGridView1_CellLeave(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellLeave
            ' Se il combo è istanziato, e la colonna è la seconda, eseguiamo il Dispose del combo, per scaricarlo
            If Not (IsNothing(combo)) And e.ColumnIndex = 1 Then combo.Dispose()
        End Sub
    
        ' Handler che controlla la selezione sulla combo
        Private Sub SelezioneCombo(sender As Object, e As System.EventArgs)
            ' Se il combo è istanziato, allora facciamo in modo che il valore della cella venga prelevato dalla selezione in combo
            ' in questo modo, dopo essere usciti dalla combo la cella manterrà il valore selezionato
            If Not (IsNothing(combo)) Then DataGridView1.CurrentCell.Value = combo.SelectedItem
        End Sub

    Il risultato, in pratica, è come in figura: nella prima Row vedi due celle di testo, perché il Focus l'ho dato sulla seconda Row. Sono posizionato sulla ColumnIndex = 1 della seconda riga, ed il codice di cui sopra me la fa quindi apparire come una combo.

    Spero di esserti stato utile


    Emiliano Musso // Microsoft MVP .NET

    mercoledì 29 luglio 2015 15:06
    Moderatore

Tutte le risposte

  • riscrivo il pezzo di codice finale che mi è partito mentre cercavo di identarlo di modo che si potesse capire il più possibile:

    il mio codice (e purtroppo non so renderlo autonomo dal progetto) è questo:

     'Evento generato quando viene visualizzato un controllo per la modifica di una cella
      Private Sub dgvListato_EditingControlShowing(ByVal sender As System.Object,

                                                ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs)

                                                Handles dgvListato.EditingControlShowing
           

            Dim cbMotori_datagridview_cell As New DataGridViewComboBoxCell
            cbMotori_datagridview_cell.Items.AddRange("BASE", "ARM1", "ARM2", "WRST", "CLAW")

            Dim X_Origine_Cella As Integer = dgvListato.CurrentCellAddress.X
            Dim Y_Origine_Cella As Integer = dgvListato.CurrentCellAddress.Y
            Dim Origine_cella As New Point(X_Origine_Cella, Y_Origine_Cella)

            ' voglio aggiungere cbMotori_datagridview_cell con origine nella cella e con la larghezza della cella: si può?

            come?    

           '...  ho provato un sacco di strade ma a tentoni...qualcuno perfavore mi può dare la dritta giusta :-)
        End Sub

    mercoledì 29 luglio 2015 14:37
  • spero si possa capire...(forse ricopiandolo su visual studio) e riordinandolo:

    se potete farmi questa cortesia ve ne sarei molto grato.

    max

    mercoledì 29 luglio 2015 14:40
  • Spero di aver ben capito la problematica: in sostanza, mantenere una cella come di semplice testo, ma poi - entrando in essa - poter scegliere da una tendina.

    Ti propongo una soluzione che faccia comparire un ComboBox nella posizione della cella corrente, e che - tramite handler - possa compilare il valore della cella stessa.

    Credo di aver commentato il codice a sufficienza: nel dubbio fammi sapere

        Dim combo As ComboBox   ' ComboBox non ancora valorizzato
    
        ' ...In ingresso della cella
        Private Sub DataGridView1_CellEnter(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellEnter
    
            ' Se la colonna è la seconda (indice 0), ci interessa applicare il combo
            If e.ColumnIndex = 1 Then
    
                ' Istanziamo il ComboBox, e gli assegniamo gli elementi voluti
                combo = New ComboBox()
                Dim items() As String = {"BASE", "ARM1", "ARM2", "WRST", "CLAW"}
                combo.Items.AddRange(items)
    
                ' Calcoliamo il rettangolo che rappresenta lo spazio della cella attuale, ed assegnamo al combo
                ' la Location e la Size corrispondenti, in modo che occupi l'intera cella
                Dim r As Rectangle = DataGridView1.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, True)
                combo.Location = New Point(r.X, r.Y)
                combo.Size = New Size(r.Width, r.Height)
    
                ' Aggiungiamo un handler per fare in modo di controllare la selezione sul combo
                AddHandler combo.SelectedIndexChanged, AddressOf SelezioneCombo
    
                ' L'eventuale valore di cella deve essere trasferito come testo del combo
                combo.SelectedItem = DataGridView1.CurrentCell.Value
    
                ' Aggiungiamo il combo alla griglia
                DataGridView1.Controls.Add(combo)
            End If
        End Sub
    
        ' ... in uscita dalla cella
        Private Sub DataGridView1_CellLeave(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellLeave
            ' Se il combo è istanziato, e la colonna è la seconda, eseguiamo il Dispose del combo, per scaricarlo
            If Not (IsNothing(combo)) And e.ColumnIndex = 1 Then combo.Dispose()
        End Sub
    
        ' Handler che controlla la selezione sulla combo
        Private Sub SelezioneCombo(sender As Object, e As System.EventArgs)
            ' Se il combo è istanziato, allora facciamo in modo che il valore della cella venga prelevato dalla selezione in combo
            ' in questo modo, dopo essere usciti dalla combo la cella manterrà il valore selezionato
            If Not (IsNothing(combo)) Then DataGridView1.CurrentCell.Value = combo.SelectedItem
        End Sub

    Il risultato, in pratica, è come in figura: nella prima Row vedi due celle di testo, perché il Focus l'ho dato sulla seconda Row. Sono posizionato sulla ColumnIndex = 1 della seconda riga, ed il codice di cui sopra me la fa quindi apparire come una combo.

    Spero di esserti stato utile


    Emiliano Musso // Microsoft MVP .NET

    mercoledì 29 luglio 2015 15:06
    Moderatore
  • ti ringrazio infinitamente: non potevo chiedere di meglio (ho cercato tanto, ma così ben spiegato e calzante non l'ho proprio trovato :-)   )

    me lo studio subito. Grazie grazie grazie

    mercoledì 29 luglio 2015 15:15
  • Felice di essere stato di aiuto.

    Tieni presente che lo stesso principio è utilizzabile per qualsiasi altro controllo: ad esempio, supponi di voler utilizzare una cella per far indicare una data. Basterà allora sostituire il ComboBox con un DateTimePicker, e modificare l'handler affinché ricavi il valore da scrivere in cella da uno dei metodi del controllo stesso, come ad esempio ToShortDateString.


    Emiliano Musso // Microsoft MVP .NET

    venerdì 31 luglio 2015 06:38
    Moderatore
  • Scusami Emiliano (grazie ancora per il precedente aiuto) (e chi volesse intervenire...a tutti un grazie anticipato dell'attenzione ).

    Come dicevi tu ho replicato il ragionamento ed il codice da te scritto e va tutto bene...sono contento.

    Mi sono accorto che indipendentemente, dal codice che va bene, se faccio eseguo un click od un doppio click e quindi non sono entrato in edit nel controllo ho comunque modo di scrivere nella cella e la cella prende poi quanto scritto che può essere sbagliato (ora ho ancora da provare se viene analizzato dal validating...perchè non mi interessa: non voglio poter scrivere se non una volta che sono in edit con il controllo).

    Ora nel dubbio di essermi spiegato non sufficientemente bene e nell'intento di non far fare fatiche immense a capire alle persone che mi vogliono aiutare rispiego con altre parole:

    -la datagridview contiene anche delle celle di valori interi.

    -Tali celle sono associate a dei controlli updown.

    -se seleziono con un click una di queste celle la riga si evidenzia e se io scrivo non vedo cosa scrivo ma se poi esco dalla riga vedo nella cella quanto scritto

    -se faccio due click mi si apre il controllo updown dentro la cella ma non è attivo. Se scrivo non vedo cosa scrivo ma se poi esco dalla cella-riga vedo quanto scritto

    -se invece faccio tre click entro nel controllo ed esso si abilita e posso scrivere vedendo ciò che scrivo e lo posso fare anche tramite il controllo.

    Tenendo conto che avete solo la mia descrizione e non il programma sotto le mani riuscite ad intuire l'origine del problema che mi assilla. Logicamente io ho fatto diverse prove prima di scrivere, ma ora non saprei proprio cosa fare.

    Un grazie dell'attenzione.

    max

    giovedì 6 agosto 2015 07:43