none
Errore gravissimo nel controllo CheckBox RRS feed

  • Domanda

  • Dopo due anni di lavoro credo di aver scoperto un grave malfunzionamento nel Controllo <BindingSource> di VisualStudio 2005.

    Per una sicura conferma ho implementato il programma di prova esposto di seguito da cui è possibile rilevare dove e come si verifica.

    La finestra di DataEntry è composta da una Form contenente:

    • 3 controlli TextBox per la visualizzazione e inserimento dei dati
    • 1 controllo CheckBox per impostare lo stato di sospensione dei record
    • 1 controllo DataGridView per visualizzare la lista dei record
    • 1 controllo BindingNavigator per operare la navigazione tra i record e i comandi di Inserimento, Modifica e Cancellazione dei dati
    • 1 controllo BindingSource per gestire il contenuto della Tabella

    Il programma è volutamente semplificato in modo da lasciare tutta la gestione della procedura ai due controlli BindingSource e BindingNavigator debitamente collegati.

    Il controllo DataGridView è stato utilizzato solamente per visualizzare il risultato delle varie operazioni.

    I pulsanti standard

    La riga di programma evidenziata in giallo è causa del malfunzionamento.


    Public Class Form6

        Dim   strConn As String   =

            "Provider=Microsoft.Jet.OLEDB.4.0;Data   Source=e:\database\Vendite.mdb"

        Dim cn As   OleDb.OleDbConnection     ' Connessione

        Dim ds As DataSet                   '   Data Set

        Dim da As OleDb.OleDbDataAdapter    ' DataAdapter

        Sub New()

            ' Chiamata richiesta da Progettazione Windows Form.

              InitializeComponent()

            ' Aggiungere le eventuali istruzioni di inizializzazione

            '   dopo la chiamata a InitializeComponent().

            ds = New

            da = New   OleDb.OleDbDataAdapter("SELECT * FROM   Prodotti", strConn)

            da.Fill(ds, "Prodotti")

        End Sub

        Private Sub Form6_Load(ByVal   sender As System.Object, _

                               ByVal e As   System.EventArgs) Handles MyBase.Load

            ' collega binding al   dataset sulla tabella Prodotti

            With BindingSource

                .DataSource = ds.Tables("Prodotti")

                .Sort = "NomeProdotto   ASC"

            End With

            txtId.DataBindings.Add("Text", BindingSource, "IDProdotto")

            txtProdotto.DataBindings.Add("Text", BindingSource, "NomeProdotto")

            txtConfezione.DataBindings.Add("Text", BindingSource, "QuantitàPerUnità")

            txtPrezzo.DataBindings.Add("InputText", BindingSource, "PrezzoUnitario")

            chkSospeso.DataBindings.Add("Checked",   BindingSource, "Sospeso")

            ' Collega   Navigatore Utenti

            BindingNavigator.BindingSource =   BindingSource

            ' Collega   DataGrid

            With   DataGridView

                .DataSource = BindingSource

                .AllowUserToAddRows = False          

                .AllowUserToDeleteRows = False     

                .AllowUserToOrderColumns = False   

                .AllowUserToResizeColumns = False  

                .AllowUserToResizeRows = False     

                .ReadOnly = True                   

                .RowHeadersVisible = False         

                ' MODALITA' DI SELEZIONE

                .SelectionMode =   DataGridViewSelectionMode.FullRowSelect         

                .MultiSelect = False                                       

                '   LAYOUT

                .AutoSizeColumnsMode =   DataGridViewAutoSizeColumnsMode.AllCells

                .AutoSizeRowsMode =   DataGridViewAutoSizeRowsMode.None

                With   .RowTemplate

                    .Height = 18

                    .MinimumHeight = 18

                    .Resizable =   DataGridViewTriState.False

                End   With

                .Columns("IDProdotto").Visible   = False

                .Columns("IDFornitore").Visible   = False

                .Columns("IDCategoria").Visible   = False

                .Columns("Scorte").Visible   = False

                .Columns("QuantitàOrdinata").Visible   = False

                .Columns("LivelloDiRiordino").Visible   = False

            End With

        End Sub

    End Class

    Collegando in Binding il controllo CheckBox si vuole poter inserire o meno un flag il cui scopo è quello di evidenziare lo stato (Sospeso/Attivo) del prodotto relativo.

    • Con la suddetta riga esclusa (Commentata) gli Inserimenti di nuove righe vanno perfettamente a buon fine (ad ogni pressione sul tasto
    • Con la suddetta riga inserita, la pressione sul tasto

    Dopo svariate prove, ho potuto constatare che solo i controlli CheckBox e OptionBox provocano questo malfunzionamento quando collegati in Binding da programma.

    P.S. Nelle guide di Visual Studio non ho trovato nessuna specifica in tal senso.

    domenica 3 maggio 2015 22:55

Risposte

  • Bello ma non è realistico.

    Provate a sostituire "List(Of Prodotto)" con un qualsiasi database e relativa connessione: il CheckBox non funziona più.

    Code First è realistico ?

    Il problema che incontri avrà a che fare con il fatto che, lavorando con il db, potresti avere a che fare con dei valori di tipo DBNull che causano errore quando si tenta di convertirli nei valori assunti dalla Checkbox. Fra vari metodi Add di DataBindings, ce ne dovrebbero essere alcuni che ti permettono di associare un valore appropriato nel caso in cui dovesse presentarsi il valore DBNull.

    mercoledì 6 maggio 2015 12:44
  • Con il CheckBox collegato in binding, sembra che qualcosa impedisca al BindingSource di gestire correttamente l'oggetto DataRowView creando si la nuova riga ma non posizionando correttamente l'oggetto Current sulla nuova riga.

    La riga aggiunta è inizialmente vuota ed il campo associato alla Checkbox sarà di tipo DBNull e genererà l'errore (controlla agganciando l'evento DataError del BindingSource)

    Per evitare questo problema, quando aggiungi il binding alla CheckBox, usa il metodo Add di DataBindings con sei parametri di cui l'ultimo indica il valore da sostituire a DBNull:

    CheckBox.DataBindings.Add("Checked", BindingSource, "Sospeso", True, DataSourceUpdateMode.OnPropertyChanged, False)

    venerdì 8 maggio 2015 06:39

Tutte le risposte

  • Dopo due anni di lavoro credo di aver scoperto un grave malfunzionamento nel Controllo <BindingSource> di VisualStudio 2005.

    Per una sicura conferma ho implementato il programma di prova esposto di seguito da cui è possibile rilevare dove e come si verifica.

    La finestra di DataEntry è composta da una Form contenente:

    • 3 controlli TextBox per la visualizzazione e inserimento dei dati
    • 1 controllo CheckBox per impostare lo stato di sospensione dei record
    • 1 controllo DataGridView per visualizzare la lista dei record
    • 1 controllo BindingNavigator per operare la navigazione tra i record e i comandi di Inserimento, Modifica e Cancellazione dei dati
    • 1 controllo BindingSource per gestire il contenuto della Tabella

    Il programma è volutamente semplificato in modo da lasciare tutta la gestione della procedura ai due controlli BindingSource e BindingNavigator debitamente collegati.

    Il controllo DataGridView è stato utilizzato solamente per visualizzare il risultato delle varie operazioni.

    I pulsanti standard

    La riga di programma evidenziata in giallo è causa del malfunzionamento.


    Public Class Form6

        Dim   strConn As String   =

            "Provider=Microsoft.Jet.OLEDB.4.0;Data   Source=e:\database\Vendite.mdb"

        Dim cn As   OleDb.OleDbConnection     ' Connessione

        Dim ds As DataSet                   '   Data Set

        Dim da As OleDb.OleDbDataAdapter    ' DataAdapter

        Sub New()

            ' Chiamata richiesta da Progettazione Windows Form.

              InitializeComponent()

            ' Aggiungere le eventuali istruzioni di inizializzazione

            '   dopo la chiamata a InitializeComponent().

            ds = New

            da = New   OleDb.OleDbDataAdapter("SELECT * FROM   Prodotti", strConn)

            da.Fill(ds, "Prodotti")

        End Sub

        Private Sub Form6_Load(ByVal   sender As System.Object, _

                               ByVal e As   System.EventArgs) Handles MyBase.Load

            ' collega binding al   dataset sulla tabella Prodotti

            With BindingSource

                .DataSource = ds.Tables("Prodotti")

                .Sort = "NomeProdotto   ASC"

            End With

            txtId.DataBindings.Add("Text", BindingSource, "IDProdotto")

            txtProdotto.DataBindings.Add("Text", BindingSource, "NomeProdotto")

            txtConfezione.DataBindings.Add("Text", BindingSource, "QuantitàPerUnità")

            txtPrezzo.DataBindings.Add("InputText", BindingSource, "PrezzoUnitario")

            chkSospeso.DataBindings.Add("Checked",   BindingSource, "Sospeso")

            ' Collega   Navigatore Utenti

            BindingNavigator.BindingSource =   BindingSource

            ' Collega   DataGrid

            With   DataGridView

                .DataSource = BindingSource

                .AllowUserToAddRows = False          

                .AllowUserToDeleteRows = False     

                .AllowUserToOrderColumns = False   

                .AllowUserToResizeColumns = False  

                .AllowUserToResizeRows = False     

                .ReadOnly = True                   

                .RowHeadersVisible = False         

                ' MODALITA' DI SELEZIONE

                .SelectionMode =   DataGridViewSelectionMode.FullRowSelect         

                .MultiSelect = False                                       

                '   LAYOUT

                .AutoSizeColumnsMode =   DataGridViewAutoSizeColumnsMode.AllCells

                .AutoSizeRowsMode =   DataGridViewAutoSizeRowsMode.None

                With   .RowTemplate

                    .Height = 18

                    .MinimumHeight = 18

                    .Resizable =   DataGridViewTriState.False

                End   With

                .Columns("IDProdotto").Visible   = False

                .Columns("IDFornitore").Visible   = False

                .Columns("IDCategoria").Visible   = False

                .Columns("Scorte").Visible   = False

                .Columns("QuantitàOrdinata").Visible   = False

                .Columns("LivelloDiRiordino").Visible   = False

            End With

        End Sub

    End Class

    Collegando in Binding il controllo CheckBox si vuole poter inserire o meno un flag il cui scopo è quello di evidenziare lo stato (Sospeso/Attivo) del prodotto relativo.

    • Con la suddetta riga esclusa (Commentata) gli Inserimenti di nuove righe vanno perfettamente a buon fine (ad ogni pressione sul tasto
    • Con la suddetta riga inserita, la pressione sul tasto

    Dopo svariate prove, ho potuto constatare che solo i controlli CheckBox e OptionBox provocano questo malfunzionamento quando collegati in Binding da programma.

    P.S. Nelle guide di Visual Studio non ho trovato nessuna specifica in tal senso.

    Le Checkbox funzionano:

    Imports System.Data
    
    Public Class Form1
    
        Dim list As New List(Of Prodotto)
    
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    
            Dim p As Prodotto
            p = New Prodotto()
            p.Prodotto = "aaa"
            p.Sospeso = True
            list.Add(p)
    
            p = New Prodotto()
            p.Prodotto = "bbb"
            p.Sospeso = False
            list.Add(p)
    
            p = New Prodotto()
            p.Prodotto = "ccc"
            p.Sospeso = True
            list.Add(p)
    
            BindingSource1.DataSource = list
            BindingSource1.Sort = "Prodotto"
    
            TextBox1.DataBindings.Add("Text", BindingSource1, "Prodotto")
            CheckBox1.DataBindings.Add("Checked", BindingSource1, "Sospeso")
    
            BindingNavigator1.BindingSource = BindingSource1
    
    
            With DataGridView1
                .DataSource = BindingSource1
                .AllowUserToAddRows = False
                .AllowUserToDeleteRows = False
                .AllowUserToOrderColumns = False
                .AllowUserToResizeColumns = False
                .AllowUserToResizeRows = False
                .ReadOnly = True
                .RowHeadersVisible = False
            End With
        End Sub
    End Class
    
    Class Prodotto
    
        Dim m_prodotto As String
        Public Property Prodotto() As String
            Get
                Return m_prodotto
            End Get
            Set(ByVal value As String)
                m_prodotto = value
            End Set
        End Property
    
        Dim m_sospeso As Boolean
        Public Property Sospeso() As Boolean
            Get
                Return m_sospeso
            End Get
            Set(ByVal value As Boolean)
                m_sospeso = value
            End Set
        End Property
    
    End Class
    

    martedì 5 maggio 2015 06:38
  • Ciao Mauro,

    come è definita nel tuo database la colonna "Sospeso". Da quello che mi pare di aver capito, vanno in errore i tuoi tentativi di salvataggio di nuovi record, come se il databinding non andasse tra la tua proprietà Checked = true/false e il relativo tipo nel DataBase. Che eccezione ti restituisce ?

    Come vedi il tipo .net boolean va mappato su un tipo sql bit...
    martedì 5 maggio 2015 09:23
  • Bello ma non è realistico.

    Provate a sostituire "List(Of Prodotto)" con un qualsiasi database e relativa connessione: il CheckBox non funziona più.

    mercoledì 6 maggio 2015 08:17
  • Non è un problema di tipo di dato. E' proprio un problema che si verifica solo quando è collegato un database.
    mercoledì 6 maggio 2015 08:21
  • Bello ma non è realistico.

    Provate a sostituire "List(Of Prodotto)" con un qualsiasi database e relativa connessione: il CheckBox non funziona più.

    Code First è realistico ?

    Il problema che incontri avrà a che fare con il fatto che, lavorando con il db, potresti avere a che fare con dei valori di tipo DBNull che causano errore quando si tenta di convertirli nei valori assunti dalla Checkbox. Fra vari metodi Add di DataBindings, ce ne dovrebbero essere alcuni che ti permettono di associare un valore appropriato nel caso in cui dovesse presentarsi il valore DBNull.

    mercoledì 6 maggio 2015 12:44
  • Ti ringrazio per il tuo suggerimento ma purtroppo ti devo specificare meglio il problema:

    Con il database collegato ed il binding in funzione riesco a navigare correttamente. il BindingNavigator esplora le righe della tabella posta in DataSet visualizzandomi tutti i dati nei controlli collegati compreso il CheckBox.

    Al momento di inserire un nuovo prodotto, si agisce sul pulsante ADD del BindingNavigator il quale chiama il metodo AddNew per avviare la creazione di una nuova riga. Infatti, la proprietà Current dell'oggetto BindingSource dovrebbe essere impostata sull'oggetto DataRowView contenente la nuova riga dei dati. 

    Effettivamente, se non ho il controllo CheckBox collegato in binding, posso inserire i dati nei controlli e con il tasto Invio posso registrare il movimento nella IList.

    Con il CheckBox collegato in binding, sembra che qualcosa impedisca al BindingSource di gestire correttamente l'oggetto DataRowView creando si la nuova riga ma non posizionando correttamente l'oggetto Current sulla nuova riga.

    E' chiaro che con tutto questo, il database viene solo scaricato nel dataSet e non viene assolutamente aggiornato o modificato.

    Se per per puro spirito investigativo vuoi provare a sostituire List(Of Prodotto) con un dataset e una tabella potrai constatare quanto si verifica.


    Nel frattempo ti ringrazio per il tempo che mi stai dedicando.
    giovedì 7 maggio 2015 23:29
  • Con il CheckBox collegato in binding, sembra che qualcosa impedisca al BindingSource di gestire correttamente l'oggetto DataRowView creando si la nuova riga ma non posizionando correttamente l'oggetto Current sulla nuova riga.

    La riga aggiunta è inizialmente vuota ed il campo associato alla Checkbox sarà di tipo DBNull e genererà l'errore (controlla agganciando l'evento DataError del BindingSource)

    Per evitare questo problema, quando aggiungi il binding alla CheckBox, usa il metodo Add di DataBindings con sei parametri di cui l'ultimo indica il valore da sostituire a DBNull:

    CheckBox.DataBindings.Add("Checked", BindingSource, "Sospeso", True, DataSourceUpdateMode.OnPropertyChanged, False)

    venerdì 8 maggio 2015 06:39
  • Eureka.

    Il tuo suggerimento è stato propedeutico, è bastato cambiare l' istruzione in:

    CheckBox.DataBindings.Add("Checked", BindingSource, "Sospeso", True)

    e tutto funziona perfettamente.

    Però non ho capito questi parametri aggiunti anche perché non ho trovato alcuna informazione.

    Dove trovo delle informazioni esaustive.

    Un ulteriore grazie.

    venerdì 8 maggio 2015 07:49
  • Eureka.

    Il tuo suggerimento è stato propedeutico, è bastato cambiare l' istruzione in:

    CheckBox.DataBindings.Add("Checked", BindingSource, "Sospeso", True)

    e tutto funziona perfettamente.

    Però non ho capito questi parametri aggiunti anche perché non ho trovato alcuna informazione.

    Dove trovo delle informazioni esaustive.

    Un ulteriore grazie.

    Nella classe Binding

    https://msdn.microsoft.com/en-us/library/system.windows.forms.binding%28v=vs.110%29.aspx

    venerdì 8 maggio 2015 08:05
  • Ancora grazie e alla prossima!

    Tutto a posto.

    venerdì 8 maggio 2015 11:10