none
Verbindung DatagridView - BindingSource eventuell fehlerhaft RRS feed

  • Frage

  • Hallo zusammen!

    Folgendes Problem:
    Ich habe eine DataTable mit einem Feld 'Zeile', das die jeweilige Zeilennummer der Datensätze enthält und nach dem die Table aufsteigend sortiert ist. Sie hat bspw. 8 Datensätze.
    Eine Bindingsource wird definiert mit
    Bindingsource.Datasource = DataTable
    und mit Filter
    Bindingsource.Filter = "Zeile > " & sAnz.Tostring
    (mit sAnz ist eine Datensatzanzahl der anzuzeigenden 'letzten' Sätze der Tabelle, also bspw.  4 bedeutet, die letzten 4 Datensätze, die in einem Datagridview angezeigt werden sollen)
    Das DatagridView wird definiert mit
    DatagridView.DataSource = BindingSource

    Der Filter funktioniert beim ersten Laden der Bindingsource und verbinden mit dem DatagridView, es werden die letzten 4 Datensätze der Table angezeigt.

    Nun ändere ich mit einem NumericUpDown-Control die Anzahl sAnz.
    Damit ändere ich auch den Filter, weil sAnz sich bspw. ändert auf 5.
    Allerdings funktioniert jetzt nichts.
    Im DatagridView wird auschließlich nur die einzelne Zeile 5 angezeigt und nicht (wie beim ersten Laden richtig) die letzten 5 Datensätze der Table.
    Ich sehe keinen Fehler in der Programmierung....

    Grüße-


    Dietrich

    Montag, 7. Januar 2019 10:33

Alle Antworten

  • Zur Illustration des Problems zwei Bilder (ganz rechts die in einem Datenfeld mitgeführte Zeilennummer der Datensätze):
    1. Anwendung des Filters nach erstem Start des Programms und Laden der Table und des DGV im Ereignis Load der Form:

    Das DGV zeigt die letzten 4 Sätze der Table richtig gemäß Filter der Bindingsource an.

    2. Nach Änderung der Anzahl der anzuzeigenden Sätze auf 5 und Anwendung des geänderten Filters sieht man nicht die letzten 5 Sätze sondern nur den fünften Satz:

    Grüße-


    Dietrich

    Dienstag, 8. Januar 2019 09:03
  • Hallo Dietrich,

    stell doch bitte ein Minimalprojekt zusammen, mit dem man das Problem selbst nachstellen kann. Das wäre sehr hilfreich, um dir bei deinem Problem helfen zu können.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET (2001-2018)
    https://www.asp-solutions.de/ - IT Beratung, Softwareentwicklung, Remotesupport

    Dienstag, 8. Januar 2019 09:35
    Moderator
  • Hi Dietrich,
    mit einem Minimalprojekt kann ich Dein Problem nicht reproduzieren. Da wird wohl in Deinem Projekt ein Problem sein. Hier meine Demo.

    Public Class Form1
      Private WithEvents tb As New TextBox With {.Dock = DockStyle.Top}
      Private dgv As New DataGridView With {.Dock = DockStyle.Fill}
      Private bs As New BindingSource
    
      Private Sub Form57_Load(sender As Object, e As EventArgs) Handles Me.Load
        Me.Controls.AddRange(New Control() {Me.dgv, Me.tb})
        Me.bs.DataSource = Me.GetData()
        Me.dgv.DataSource = Me.bs
      End Sub
    
      Private Sub tb_TextChanged(sender As Object, e As EventArgs) Handles tb.TextChanged
        If IsNumeric(tb.Text) Then
          Me.bs.Filter = $"ID > {Me.tb.Text}"
        Else
          Me.bs.Filter = String.Empty
        End If
      End Sub
    
      Private Function GetData() As DataTable
        Dim dt As New DataTable
        dt.Columns.Add("ID", GetType(Integer))
        dt.Columns.Add("Info", GetType(String))
        For i = 1 To 9
          dt.Rows.Add(i, $"Zeile {i}")
        Next
        Return dt
      End Function
    
    End Class


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP für Developer Technologies)
    Meine Homepage mit Tipps und Tricks


    Dienstag, 8. Januar 2019 20:45
  • Hallo Peter und Stefan, für Miniprojekt brauche ich ein wenig Zeit...
    Grüße-

    Dietrich

    Mittwoch, 9. Januar 2019 08:31
  • Hallo Peter,

    mit kleinen Änderungen deines Codes funktioniert dein Bespiel.

    Public Class Form13
    
    	Private WithEvents tb As New TextBox With {.Dock = DockStyle.Top}
    	Private dgv As New DataGridView With {.Dock = DockStyle.Fill}
    	Private bs As New BindingSource
    
    	Private Sub Form57_Load(sender As Object, e As EventArgs) Handles Me.Load
    		Me.Controls.AddRange(New Control() {Me.dgv, Me.tb})
    		Me.bs.DataSource = Me.GetData()
    		Me.dgv.DataSource = Me.bs
    	End Sub
    
    	Private Sub tb_TextChanged(sender As Object, e As EventArgs) Handles tb.TextChanged
    		If IsNumeric(tb.Text) And tb.Text <> "" Then
    			Me.bs.Filter = $"Info > {Me.tb.Text}"
    		Else
    			Me.bs.Filter = String.Empty
    		End If
    	End Sub
    
    	Private Function GetData() As DataTable
    		Dim dt As New DataTable
    		dt.Columns.Add("ID", GetType(Integer))
    		dt.Columns.Add("Info", GetType(String))
    		For i = 1 To 9
    			dt.Rows.Add(i, i)
    		Next
    		Return dt
    	End Function
    
    End Class

    Allerdings mache ich es in meinem Programm prinzipiell gleich, nur dass die Tabellendaten und die Zeilennummern aus einer SQL-Tabelle kommen mittels:

    "SELECT * " _
    	+ "ROW_NUMBER() OVER (ORDER BY ID ASC) AS Zeile " _
    	+ "FROM myTableName ORDER BY Zeile"
    Grüße-


    Dietrich

    Mittwoch, 9. Januar 2019 09:16
  • Hi Dietrich,
    Deine Änderung 

    If IsNumeric(tb.Text) Then

    in

    If IsNumeric(tb.Text) And tb.Text <> "" Then

    ist nicht notwendig, da IsNumeric auch für eine leere Zeichenkette False ergibt. Du bekommst also für eine leere Zeichenkette eine Bedingung "False And False", die wegen dem ersten False IMMER False ergibt, so dass die zweite Bedingung nicht erforderlich ist.

    For den Filter der Sicht (aus der BindingSource) ist es völlig egal, wo die Daten herkommen. Vermutlich greift Dein Filter nicht auf das zu, was Du Dir vorstellst.


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP für Developer Technologies)
    Meine Homepage mit Tipps und Tricks

    Mittwoch, 9. Januar 2019 09:43
  • Also ich MUSSTE das AND einfügen, denn sonst kam Fehlerausschrift in der Zeile
    Me.bs.Filter = $"Info > {Me.tb.Text}", und zwar System.Data.SyntaxErrorException: "Syntaxfehler: Fehlender Operand nach dem Operator '>'."

    Aber egal, ich werde mal noch von meinem Code was posten, demnächst.

    Grüße-

    Dietrich

    Mittwoch, 9. Januar 2019 09:58
  • Hi Dietrich,
    wenn IsNumeric(Me.tb.Text) wegen Me.tb.Text="" False ergibt, kommt das Programm nicht in den Zweig mit der Filterzuweisung: 

    Me.bs.Filter = $"Info > {Me.tb.Text}"

    Da solltest Du mal ein Debug machen. Wenn bei Dir IsNumeric anders arbeitet, dann prüfe mal die Framework-Version. Bei mir ist es die 4.7. Ggf. ist auch Deine Installation zerstört, was ich mir aber nicht vorstellen kann.


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP für Developer Technologies)
    Meine Homepage mit Tipps und Tricks

    Mittwoch, 9. Januar 2019 10:33
  • Bei mir Framework 4.6.1
    Und zehn Minuten bevor ich deinen Code probierte war das Update von VS2017 auf Version 15.9.5. gelaufen.

    Grüße-


    Dietrich

    Mittwoch, 9. Januar 2019 10:42
  • Hallo Peter, eine Variante deines Codes mit NumericUpDown:

    Public Class Form13
    
    	Private WithEvents tb As New TextBox 'With {.Dock = DockStyle.Top}
    	Private dgv As New DataGridView With {.Dock = DockStyle.Fill}
    	Private bs As New BindingSource
    	Private WithEvents anz As New NumericUpDown With {.Dock = DockStyle.Top}
    
    	Private Sub Form57_Load(sender As Object, e As EventArgs) Handles Me.Load
    		Me.Controls.AddRange(New Control() {Me.dgv, Me.anz})
    		Me.bs.DataSource = Me.GetData()
    		Me.dgv.DataSource = Me.bs
    		Me.dgv.AllowUserToAddRows = False
    		With Me.anz
    			.Maximum = bs.Count
    			.Minimum = 1
    			.Value = 1
    		End With
    	End Sub
    
    	Private Sub tb_TextChanged(sender As Object, e As EventArgs) Handles tb.TextChanged
    		If IsNumeric(tb.Text) And tb.Text <> "" Then
    			Me.bs.Filter = $"Info > {Me.tb.Text}"
    		Else
    			Me.bs.Filter = String.Empty
    		End If
    	End Sub
    
    	Private Sub anz_ValueChanged(sender As Object, e As EventArgs) Handles anz.ValueChanged
    		Me.bs.Filter = $"Info >= {Me.anz.Value}"
    	End Sub
    
    	Private Function GetData() As DataTable
    		Dim dt As New DataTable
    		dt.Columns.Add("ID", GetType(Integer))
    		dt.Columns.Add("Info", GetType(String))
    		For i = 1 To 9
    			dt.Rows.Add(i, i)
    		Next
    		Return dt
    	End Function
    
    End Class


    Dietrich

    Mittwoch, 9. Januar 2019 11:06
  • Hi Dietrich,
    Dein Beispiel funktioniert bei mir mit der Änderung, dass ich den Filter numerisch setze, also  Me.bs.Filter = $"ID >= {Me.anz.Value}"
    Public Class Form1
      Private WithEvents tb As New TextBox With {.Dock = DockStyle.Top}
      Private dgv As New DataGridView With {.Dock = DockStyle.Fill}
      Private bs As New BindingSource
      Private WithEvents anz As New NumericUpDown With {.Dock = DockStyle.Top}
    
      Private Sub Form57_Load(sender As Object, e As EventArgs) Handles Me.Load
        Me.Controls.AddRange(New Control() {Me.dgv, Me.anz, Me.tb})
        Me.bs.DataSource = Me.GetData()
        Me.dgv.DataSource = Me.bs
      End Sub
    
      Private Sub tb_TextChanged(sender As Object, e As EventArgs) Handles tb.TextChanged
        If IsNumeric(tb.Text) Then
          Me.bs.Filter = $"ID > {Me.tb.Text}"
        Else
          Me.bs.Filter = String.Empty
        End If
      End Sub
    
      Private Sub anz_ValueChanged(sender As Object, e As EventArgs) Handles anz.ValueChanged
        Me.bs.Filter = $"ID >= {Me.anz.Value}"
      End Sub
    
      Private Function GetData() As DataTable
        Dim dt As New DataTable
        dt.Columns.Add("ID", GetType(Integer))
        dt.Columns.Add("Info", GetType(String))
        For i = 1 To 9
          dt.Rows.Add(i, $"Zeile {i}")
        Next
        Return dt
      End Function
    
    End Class
    
    




    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP für Developer Technologies)
    Meine Homepage mit Tipps und Tricks

    Mittwoch, 9. Januar 2019 12:06