Jump to content
Sign in to follow this  
arrelialp

ComboBox Column

Recommended Posts

arrelialp

Viva,

Criei uma DataGridview na qual tenho 4 colunas. A 4.ª coluna é um ComboBoxColumn em que em cada uma das células desta coluna o utilizador pode escolher, da lista de valores, a seguinte opção: "É Chave" (pois, só tem uma opção porque para este caso não vale a pena ter a opção "Não Chave").

Precisava da vossa ajuda para que, a partir do momento que uma célula desta coluna já tivesse a informação "É Chave" não aparecesse mais a possibilidade de inserir nas outras células "É Chave". Só se na célula que que já "É Chave" fosse retirada esta informação.

O código que tenho é o seguinte:

Private Sub AdicionarComboBoxColumns()

        Dim comboboxColumn As DataGridViewComboBoxColumn

         comboboxColumn = CriarComboBoxColumn()

        SetUsingItems(comboboxColumn)

        comboboxColumn.HeaderText = _

            "Chave_Primaria"

        tabelaDataGridView.Columns.Add(comboboxColumn)

    End Sub
Private Function CriarComboBoxColumn() _

        As DataGridViewComboBoxColumn

        Dim column As New DataGridViewComboBoxColumn()

        With column

            .FlatStyle = FlatStyle.Flat

        End With

        Return column

    End Function
Private Shared Sub SetUsingItems( _

        ByVal comboboxColumn As DataGridViewComboBoxColumn)

        comboboxColumn.Items.AddRange("É Chave!")

    End Sub

Agradeço desde já a ajuda  :)

Share this post


Link to post
Share on other sites
Caça

Queres limitar as escolhas possíveis na combobox para uma determinada linha?


Pedro Martins

Não respondo a duvidas por PM

Share this post


Link to post
Share on other sites
arrelialp

Não. Se numa linha já estiver inserido na 4.ª coluna "É Chave!", nas outras linhas na 4.ª coluna já não pode aparecer esta escolha, como podes ver pela seguinte imagem:

tabelarx.jpg

Agora nas restantes linhas, e uma vez que já indiquei na primeira que é campo chave, não poderá aparecer esta possibilidade, a não ser que o utilizador regresse outra vez à primeira linha e apague "É chave!" (mas também já verifiquei que, uma vez inserido "É Chave!" da lista de valores, já não consigo apagar o valor desta célula  🤔 ).

Não sei se me fiz entender. Qual será a melhor forma para implementar isto?

Share this post


Link to post
Share on other sites
Caça

Tens de adicionar todos os itens possíveis a ComboBox, depois tens de utilizar o evento EditingControlShowing da DataGridView para limitar os itens disponíveis, ai tens de verificar se alguma das linhas já tem esse item adicionado, se sim, não o mostras.


Pedro Martins

Não respondo a duvidas por PM

Share this post


Link to post
Share on other sites
arrelialp

Não domino isto.

Já coloquei todos os itens à ComboBox, como indicaste, e iniciei com este código.

Private Sub tabelaDataGridView_EditingControlShowing(ByVal sender As Object, _
      ByVal e As DataGridViewEditingControlShowingEventArgs) _
      Handles tabelaDataGridView.EditingControlShowing
          For Each L As DataGridViewRow In Me.tabelaDataGridView.Rows
              If L.IsNewRow Then Exit For
               IF e.control. = .....SERÀ?            
          Next

    
    End Sub

Podes-me ajudar com algum código?

Share this post


Link to post
Share on other sites
Caça

Será tipo isto

        If TypeOf e.Control Is System.Windows.Forms.DataGridViewComboBoxEditingControl Then
            For Each L As DataGridViewRow In Me.tabelaDataGridView.Rows
                If L.IsNewRow Then Exit For
                If L.Cells(3).Value = "É Chave!" Then
                    Dim L As New List(Of String)

                    'Só deixo que estes sejam mostrados, deves adicionar todos menos o "É Chave!"
                    L.Add("Opção 1")
                    L.Add("Opção 2")
                    L.Add("Opção 3")

                    Dim C As System.Windows.Forms.ComboBox = CType(e.Control, System.Windows.Forms.ComboBox)
                    C.DataSource = L

                    Exit For
                End If
            Next

        End If


Pedro Martins

Não respondo a duvidas por PM

Share this post


Link to post
Share on other sites
arrelialp

Hummm, está-me a dar o seguinte erro: Variable 'L' hides a variable in an enclosing block.

Share this post


Link to post
Share on other sites
José Lopes

Não foi no teu código...estava a responder ao último post...nem a dica era obviamente para ti ;-)


Quando te pedirem peixe.... ensina-os a Pescar!!Hum..lálálálá!!

Share this post


Link to post
Share on other sites
arrelialp

Viva,

Reparei agora que uma outra ComboBoxColumn que tenho está a assumir na sua lista de valores, os valores que vêm desta ComboBox, depois do utilizador seleccionar, dentro da lista de valores, o valor "Chave".

Como poderei solucionar esta situação? O código até agora é o seguinte:


Private Sub tabelaDataGridView_EditingControlShowing(ByVal sender As Object, _

    ByVal e As DataGridViewEditingControlShowingEventArgs) _

    Handles tabelaDataGridView.EditingControlShowing

        If TypeOf e.Control Is System.Windows.Forms.DataGridViewComboBoxEditingControl Then

            For Each M As DataGridViewRow In Me.tabelaDataGridView.Rows

                If M.IsNewRow Then Exit For

                If M.Cells(3).Value = "É Chave!" Then

                    Dim L As New List(Of String)

                    'Só deixo que estes sejam mostrados, deves adicionar todos menos o "É Chave!"

                    L.Add("Não Chave")

                    Dim C As System.Windows.Forms.ComboBox = CType(e.Control, System.Windows.Forms.ComboBox)

                    C.DataSource = L

                    Exit For

                End If

            Next

        End If

    End Sub 

Como poderei fazer com que a lista de valores fique apenas afeta à 4.ª coluna?

Share this post


Link to post
Share on other sites
Caça

Verifica se o índex da coluna selecionada é igual ao índex da coluna que queres controlar.


Pedro Martins

Não respondo a duvidas por PM

Share this post


Link to post
Share on other sites
Caça

Vais precisar de evento CellBeginEdit para apanhares o index, tipo

    Dim IndexColunaQueVaiSerEditada As Integer

    Private Sub DataGridView1_CellBeginEdit(sender As Object, e As System.Windows.Forms.DataGridViewCellCancelEventArgs) Handles DataGridView1.CellBeginEdit
        IndexColunaQueVaiSerEditada = e.ColumnIndex
    End Sub

e depois fazes a verificação, tipo

    Private Sub DataGridView1_EditingControlShowing(sender As Object, e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles DataGridView1.EditingControlShowing
        If TypeOf e.Control Is System.Windows.Forms.DataGridViewComboBoxEditingControl Then
            If IndexColunaQueVaiSerEditada = 0 Then
                'Faz o que tem a fazer para a coluna 0 
            ElseIf IndexColunaQueVaiSerEditada = 1 Then
                'Faz o que tem a fazer para a coluna 1
            Else
                '...
            End If
        End If
    End Sub


Pedro Martins

Não respondo a duvidas por PM

Share this post


Link to post
Share on other sites
arrelialp

Viva. Parece que resolveu. Estive a testar e ficou assim:

Dim IndexColunaQueVaiSerEditada As Integer
  
    Private Sub DataGridView1_CellBeginEdit(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellCancelEventArgs) Handles tabelaDataGridView.CellBeginEdit

        IndexColunaQueVaiSerEditada = e.ColumnIndex

    End Sub
  
    Private Sub tabelaDataGridView_EditingControlShowing(ByVal sender As Object, _

    ByVal e As DataGridViewEditingControlShowingEventArgs) _

    Handles tabelaDataGridView.EditingControlShowing

        If TypeOf e.Control Is System.Windows.Forms.DataGridViewComboBoxEditingControl Then

            If IndexColunaQueVaiSerEditada = 3 Then

                For Each M As DataGridViewRow In Me.tabelaDataGridView.Rows

                    If M.IsNewRow Then Exit For

                    If M.Cells(3).Value = "É Chave!" Then

                        Dim L As New List(Of String)

                        'Só deixo que estes sejam mostrados, deves adicionar todos menos o "É Chave!"

                        L.Add("Não Chave")

                        Dim C As System.Windows.Forms.ComboBox = CType(e.Control, System.Windows.Forms.ComboBox)

                        C.DataSource = L

                        Exit For

                    End If

                Next

            ElseIf IndexColunaQueVaiSerEditada = 1 Then

                'Faz o que tem a fazer para a coluna 1

            Else

                '...

            End If

        End If

    End Sub 

O que te parece? Os outros If´s nada têm pois só preciso de alterar a coluna 3. Será que poderias explicar porquê agora funciona e antes não. Deve-se ao Private Sub CellBeginEdit? Obrigado mais uma vez.

Share this post


Link to post
Share on other sites
arrelialp

Viva,

Estive a fazer mais testes com este código e não estou a conseguir validar o que pretendo. Gostaria de fazer o design de uma tabela em tudo (ou quase tudo) igual ao do SQL Server.

Eu pretendo que quando o utilizador seleciona "É Chave!"  numa qualquer linha, ou seja, campo M.Cells(3).Value = "É Chave!" seja obrigatório que o os campos M.Cells(2).Value = False e M.Cells(1).Value = "int" na mesma linha.

A partir do momento que exista já uma linha com o campo M.Cells(3).Value = "É Chave!" não poderá haver outra célula desta coluna que tenha M.Cells(3).Value = "É Chave!", uma vez que uma tabela só poderá ter um campo chave.

A partir daqui, ou seja, havendo um campo que já seja chave a lista de valores que aparece para este campo é apenas "Não Chave".

Share this post


Link to post
Share on other sites
Caça

A parte de não mostrar o "É Chave!" quando seleccionado já está resolvida ou não? O resto são só verificações.

Se queres fazer como no SSMS, não deves limitar o numero de chaves primarias.


Pedro Martins

Não respondo a duvidas por PM

Share this post


Link to post
Share on other sites
arrelialp

As verificações não estão a funcionar bem. E é como dizes. Gostaria de ter as validações o mais parecidas com o SSMS, se possível iguais.

Havendo um registo (linha) com um campo "É Chave!" já não pode haver outro. Para ser chave terá que o tipo de dados ser inteiro (int) e não aceitar nulos. Ou seja, neste caso:

M.Cells(1).Value = "int" and M.Cells(2).Value = False and M.Cells(3).Value = "É Chave!"

Quando estou na DataGridView, na célula M.Cells(3) e seleciono logo, da lista de valores, "É Chave!" não me está a validar os outros campos, ou seja, a obrigar que o M.Cells(2).Value = False e M.Cells(1) = "int", apenas o faz quando edito outra célula M.Cells(3)

Com a validação que tenho, apesar de funcionar relativamente bem, como está dentro do ciclo For, e depois do utilizador seleccionar "É Chave!", está-me sempre a dar a mensagem que tenho na validação, que é esta:

 MessageBox.Show("Valide se o tipo de dados é inteiro e se o não aceita valores não nulos.")

Não estou a conseguir fazer isto  :)

O código que tenho é este:

Private Sub tabelaDataGridView_EditingControlShowing(ByVal sender As Object, _

    ByVal e As DataGridViewEditingControlShowingEventArgs) _

    Handles tabelaDataGridView.EditingControlShowing

        If TypeOf e.Control Is System.Windows.Forms.DataGridViewComboBoxEditingControl Then

            If IndexColunaQueVaiSerEditada = 3 Then

                For Each M As DataGridViewRow In Me.tabelaDataGridView.Rows

                    If M.IsNewRow Then Exit For

                    If M.Cells(3).Value = "É Chave!" Then

                        MessageBox.Show("Valide se o tipo de dados é inteiro e se o não aceita valores não nulos.")

                        Dim L As New List(Of String)

                        'Só deixo que estes sejam mostrados, devo adicionar todos menos o "É Chave!"

                        L.Add("Não Chave")

                        Dim C As System.Windows.Forms.ComboBox = CType(e.Control, System.Windows.Forms.ComboBox)

                        C.DataSource = L

                        M.Cells(1).Value = "int"

                        M.Cells(2).Value = False

                        Exit For

                    End If

                Next

            ElseIf IndexColunaQueVaiSerEditada = 3 Then

                '...

            Else

                '...

            End If

        End If

    End Sub



Share this post


Link to post
Share on other sites
Caça

Para o que pretendes talvez seja melhor fazer essa validação no evento RowValidating ou RowValidated, em que caso a linha que está a ser editada seja chave, forças os outros dois campos.

A validação nesse evento não faz sentido.


Pedro Martins

Não respondo a duvidas por PM

Share this post


Link to post
Share on other sites
arrelialp

Pois  :D Exato! A validação tem que ser realizada à linha  :)

Comecei a fazer isto só que não chega...

É que depois de validar que sempre que se seleciona "É Chave!" (não sei como vou fazer isto) tenho que garantir que a célula correspondente à coluna Nulo = False e a célula correspondente à coluna Tipo_Dados = "int".

Depois, e já no evento Row Validated, é que tenho que assegurar que a lista de valores só tem o valor: "Não Chave"

Podes-me dar uma ajuda?


Private Sub ValidateByRow(ByVal sender As Object, _

        ByVal data As DataGridViewCellCancelEventArgs) _

        Handles tabelaDataGridView.RowValidating

        Dim row As DataGridViewRow = _

            tabelaDataGridView.Rows(data.RowIndex)

        'Dim CellTipoDeDados As DataGridViewCell = _

        '    row.Cells(tabelaDataGridView.Columns("Tipo_Dados").Index)

        Dim CellNull As DataGridViewCell = _

            row.Cells(tabelaDataGridView.Columns("Nulo").Index)

        data.Cancel = Not (IsNull(CellNull))

    End Sub
  
    Private Function IsTipoDeDados(ByRef cell As DataGridViewCell) As Boolean

        If cell.Value Is Nothing Then

            cell.ErrorText = "Por favor entre um tipo de dados"

            tabelaDataGridView.Rows(cell.RowIndex).ErrorText = _

                "Por favor entre um tipo de dados"

            Return False

        End If

        Return True

    End Function
  
    Private Function IsNull(ByRef cell As DataGridViewCell) As Boolean

        If cell.Value = True Then

            cell.ErrorText = "Não pode aceitar valores nulos."

            tabelaDataGridView.Rows(cell.RowIndex).ErrorText = _

                "Não pode aceitar valores nulos."

            Return False

        End If

        Return True

    End Function 

Share this post


Link to post
Share on other sites
Caça

Eu acho que não faz sentido estares a enviar mensagens ao utilizador porque o campo é int ou não...

Já que quando o campo é chave primaria tu só queres que ele seja do tipo int e não nulo, quando detectares que o valor de chave foi seleccionado altera logo os outros dois valores sem estar a pedir ao utilizador para fazê-lo, uma vez que pode ser o programa a fazer.


Pedro Martins

Não respondo a duvidas por PM

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.