Erweiterter Umgang mit typisiertem DataSet -> Tabellennamen lesen/Namensübergabe etc.

  • VB.NET
  • .NET (FX) 4.0

Es gibt 351 Antworten in diesem Thema. Der letzte Beitrag () ist von tragl.

    je nach Datentyp der Werte bastelt die Extension verschiedene FilterSegmente.
    Gib dir mal bsTourInfo.Filter aus, nachdem .FilterX() durchgelaufen ist.
    Wie lautet dieser Filter-String?
    Und welchen Datentyp haben _uGesellschaft, _setYear?
    Ach, und welche Datentypen haben die Spalten Gesellschaft, Jahr inne DataTable?

    ErfinderDesRades schrieb:

    Wie lautet dieser Filter-String?

    beim Öffnen der Form:
    klick auf Suche:
    2. Klick auf Suche:

    öffnen der Form und Suche führen für das Beispiel die gleiche Sub aus:

    VB.NET-Quellcode

    1. Private Sub bsView()
    2. Select Case checkView(_appMod)
    3. Case "Admin" : bsTourInfo.FilterX("Jahr = ?", _setYear)
    4. Case "Alles" : bsTourInfo.FilterX("Jahr = ?", _setYear)
    5. Case "Gesellschaft" : bsTourInfo.FilterX("Gesellschaft = ? AND Jahr = ?", _uGesellschaft, _setYear)
    6. Case "Standort" : bsTourInfo.FilterX("Standort = ? AND Jahr = ?", _uStandort, _setYear)
    7. End Select
    8. msgInformation(bsTourInfo.Filter)
    9. End Sub


    _uGesellschaft = String
    _setYear = Integer

    in den Tabellen entsprechend auch
    Gesellschaft = String
    Jahr = Integer
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:
    kann ich mir nicht erklären.
    Aufgerufen wird dieses:

    VB.NET-Quellcode

    1. ''' <summary>
    2. ''' provides a placeholder-syntax for filters. Sample: dv.FilterX(true, "Datum >= ? And ? >= Datum", dtpVon.Value, dtpBis.Value)
    3. ''' </summary>
    4. ''' <exception cref="ArgumentException">expression contains more placeholders than values are passed</exception>
    5. <Extension()> _
    6. Public Sub FilterX(bs As BindingSource, execute As Boolean, expression As String, ParamArray values() As Object)
    7. bs.Filter = If(execute, GetFilterString(expression, values), "")
    8. End Sub
    9. ''' <summary>
    10. ''' provides a placeholder-syntax for filters. Sample: dv.FilterX("Datum >= ? And ? >= Datum", dtpVon.Value, dtpBis.Value)
    11. ''' </summary>
    12. ''' <exception cref="ArgumentException">expression contains more placeholders than values are passed</exception>
    13. <Extension()> _
    14. Public Sub FilterX(bs As BindingSource, expression As String, ParamArray values() As Object)
    15. bs.Filter = GetFilterString(expression, values)
    16. End Sub
    17. ''' <summary> Get the FilterX()-FilterString for Debugging </summary>
    18. <Extension()> _
    19. Public Function GetFilterString(bs As BindingSource, expression As String, ParamArray values() As Object) As String
    20. Return GetFilterString(expression, values)
    21. End Function
    Das zweite Ergebnis kann eiglich nur entstehen, wenn der zweite Parameter Boolean ist, und zwar False. Dann wird die erste Methode des Snippets aufgerufen, und False sagt ihm, er solle nicht filtern.
    Guck daas mal nach, ob bei dir auch diese methoden vorhanden sind, und dass bei dir die zwiete davon aufgerufen wird.

    ErfinderDesRades schrieb:

    Aufgerufen wird dieses:


    da kann ich doch bestimmt ma probiern die Zeile
    bs.Filter = If(execute, GetFilterString(expression, values), "")
    ersetzen durch
    bs.Filter = If(execute, GetFilterString(expression, values), bs.Filter)

    weil die müsste ja aussagen (hab visual studio grad nicht offen), wenn filterx erfolgreich dann den nehmen, ansonsten bs.filter = "" wenn ich das hier richtig sehe.
    wenn ich das umschreibe würde er quasi wenn filterx nicht erfolgreich war (warum auch immer) den alten Filterwert nehmen?
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:
    klar kannste machen, ist aber nicht Idee vons das.
    Idee ist, dass man den Filter an/aus-stellen kann mit demselben Code.
    Aber ich kann das Verhalten was du hast immer weniger verstehen.
    Also sicherlich wird diese Methode aufgerufen:

    VB.NET-Quellcode

    1. ''' <summary>
    2. ''' provides a placeholder-syntax for filters. Sample: dv.FilterX("Datum >= ? And ? >= Datum", dtpVon.Value, dtpBis.Value)
    3. ''' </summary>
    4. ''' <exception cref="ArgumentException">expression contains more placeholders than values are passed</exception>
    5. <Extension()> _
    6. Public Sub FilterX(bs As BindingSource, expression As String, ParamArray values() As Object)
    7. bs.Filter = GetFilterString(expression, values)
    8. End Sub
    keine Andere. Und da wird halt ein FilterString gebaut und zugewiesen, ich kann mir nicht erklären, wieso der auf einmal weg sein sollte.

    ErfinderDesRades schrieb:

    keine Andere.


    also bei mir wird das hier aufgerufen

    VB.NET-Quellcode

    1. ''' <summary>
    2. ''' provides a placeholder-syntax for filters. Sample: dv.FilterX("Datum >= ? And ? >= Datum", dtpVon.Value, dtpBis.Value)
    3. ''' </summary>
    4. ''' <exception cref="ArgumentException">expression contains more placeholders than values are passed</exception>
    5. <Extension()>
    6. Public Sub FilterX(bs As BindingSource, expression As String, ParamArray values() As Object)
    7. Dim filter = GetFilterString(expression, values)
    8. bs.Filter = If(bs.Filter = filter, "", filter) ' GetFilterString(expression, values)
    9. End Sub


    und das besagt ja quasi: wenn bs.filter = getfilter dann "" ansonsten getfilter - würde genau das verhalten bei mir erklären
    so läuft das nun (zumindest für den einen Fall - alles Weitere muss ich dann noch testen):

    VB.NET-Quellcode

    1. ''' <summary>
    2. ''' provides a placeholder-syntax for filters. Sample: dv.FilterX("Datum >= ? And ? >= Datum", dtpVon.Value, dtpBis.Value)
    3. ''' </summary>
    4. ''' <exception cref="ArgumentException">expression contains more placeholders than values are passed</exception>
    5. <Extension()>
    6. Public Sub FilterX(bs As BindingSource, expression As String, ParamArray values() As Object)
    7. bs.Filter = GetFilterString(expression, values)
    8. 'Dim filter = GetFilterString(expression, values)
    9. 'bs.Filter = filter 'If(bs.Filter = filter, "", filter) ' GetFilterString(expression, values)
    10. End Sub

    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:
    @ErfinderDesRades:
    Ich pack' das mal hier rein, ist bestimmt für den ein oder anderen interessant.

    Hier hab ich nen Spezialfall -> ein ungebundenes DGV, was manuell befüllt wird.
    Dennoch möchte ich hier MultiEdit verfügbar machen. Soweit wie ich das sehen kann arbeitet die MultiEditMethode mit einer List(Of DataRowView)
    Spoiler anzeigen

    VB.NET-Quellcode

    1. <Extension()>
    2. Public Function EditMulti(dgv As DataGridView, dlg As Form) As DialogResult
    3. Dim bsDgv = DirectCast(dgv.DataSource, BindingSource)
    4. Dim drvs = EditMultiGetRows(dgv)
    5. 'drv0 von den anneren drvs trennen, weil gesondert zu behandeln (es ist dasjenige, welches im Dialog angezeigt wird)
    6. Dim drv0 = drvs(0)
    7. If Not drv0.IsEdit Then drv0.BeginEdit()
    8. drvs.RemoveAt(0)
    9. Dim prevValues = drv0.Row.ItemArray
    10. EditMultiPrepare(drv0, drvs)
    11. drv0.Row.Table.DataSet.Register(dlg, False)
    12. Dim bsDlg = GetBindingSourceForTable(dlg, drv0.Row.Table)
    13. bsDlg.DataSource = drv0
    14. EditMulti = dlg.ShowDialog() ' dieses legt den Rückgabewert von EditItem fest (so ist das in VB)
    15. If EditMulti = Windows.Forms.DialogResult.OK Then
    16. Dim columns = drv0.Row.Table.Columns
    17. For iCol = 0 To columns.Count - 1
    18. If columns(iCol).ReadOnly Then Continue For
    19. If drv0(iCol) Is DBNull.Value Then ' keine Änderung im Dialog -> alten Wert einsetzen
    20. drv0(iCol) = prevValues(iCol)
    21. Else ' Änderung im Dialog -> Eintrag in alle drvs
    22. For Each drv In drvs
    23. drv(iCol) = drv0(iCol)
    24. Next
    25. End If
    26. Next
    27. bsDlg.EndEdit()
    28. bsDgv.ResetCurrentItem() 'den in bsDlg geänderten Datensatz auch in bsDgv neu einlesen.
    29. Else
    30. bsDgv.CancelEdit()
    31. End If
    32. End Function


    Kannst du mir sagen, wie ich eine DataRow in einen DataRowView casten kann?
    Oder sollte ich hier anders rangehen? Ich muss ja meine selektierten Cells auslesen, davon jeweils die DataRow holen
    -> Zeile 7 wäre dann die entsprechende Row
    und die bzw. mehrere davon sollen ja zeitgleich editiert werden.

    VB.NET-Quellcode

    1. Private Sub MultiEdit()
    2. Dim lst As New List(Of DataRowView)
    3. For Each selCell As DataGridViewCell In dgv.SelectedCells
    4. If Dts.TourGebiet.Where(Function(x) x.Gebiet = dgv.Columns(selCell.ColumnIndex).Name.RightCut("|")).Count > 0 Then
    5. Dim rwGebiet = Dts.TourGebiet.First(Function(x) x.Gebiet = dgv.Columns(selCell.ColumnIndex).Name.RightCut("|"))
    6. Dim tourenplanID = convertInteger(dgv.Item($"TourPlanID|{rwGebiet.Gebiet}", selCell.RowIndex).Value)
    7. Dim rwTourenplan = Dts.Tourenplan.First(Function(x) x.ID = tourenplanID)
    8. 'rwtourenplan in datarowview casten und zu lst hinzufügen
    9. End If
    10. Next
    11. 'multiedit anstoßen
    12. 'wenn dialogresult = ok dann speichern und dgv neu befüllen, damit Änderungen sichtbar sind.
    13. End Sub
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:
    vielleicht sollte man ein MultiEdit basteln, was ein DataRow-Array editiert.
    Letztendlich kann man sowieso nur DataRows editieren - ein DataRowView ist nur ja ein Wrapper, der eine DataRow enthält.



    Eine DataRow kann man nicht in ein DataRowView casten. Du musst mal iwie recherchieren, was casten eiglich ist.
    Erklärung aus dem Bauch: Wenn der Compiler nicht weiss, welchen Typ ein Objekt hat, dann kann man ihm das per Cast mitteilen.
    Oder anners: Ein Cast zwingt den Compiler, ein beliebiges Objekt unbestimmten typs zu behandeln, als sei es von einem bestimmten - im Cast angegebenen - Typ.
    Das funktioniert nur, wenn das Objekt wirklich von diesem Typ ist - ist es von einem anderen Typ, scheitert der Cast.

    Eine DataRow ist aber kein DataRowView. Kann es niemals sein. Ein DatarowView enthält eine DataRow - sie ist aber keine DataRow.

    Du kannst die DataRow aus einem DataRowView herausholen - kein Problem: drv.DataRow
    Aber aus einer DataRow kannste natürlich kein DataRowView herausholen.
    Aus dem Wasser kann man nicht herausholen, in welchem Eimer es war.

    @ErfinderDesRades:

    Hab's jetzt mal so versucht:

    Spoiler anzeigen

    Visual Basic-Quellcode

    1. <Extension()>
    2. Public Function EditMulti(dgv As DataGridView, dlg As Form, drs As List(Of DataRow)) As DialogResult
    3. 'dr0 von den anneren drs trennen, weil gesondert zu behandeln (es ist dasjenige, welches im Dialog angezeigt wird)
    4. Dim dr0 = drs(0)
    5. If dr0.RowState = DataRowState.Unchanged Then dr0.BeginEdit() 'für DataRow gibt es kein "IsEdit"
    6. drs.RemoveAt(0)
    7. Dim prevValues = dr0.ItemArray
    8. EditMultiPrepare(dr0, drs)
    9. dr0.Table.DataSet.Register(dlg, False)
    10. Dim bsDlg = GetBindingSourceForTable(dlg, dr0.Table)
    11. bsDlg.DataSource = dr0
    12. EditMulti = dlg.ShowDialog() ' dieses legt den Rückgabewert von EditItem fest (so ist das in VB)
    13. If EditMulti = Windows.Forms.DialogResult.OK Then
    14. Dim columns = dr0.Table.Columns
    15. For iCol = 0 To columns.Count - 1
    16. If columns(iCol).ReadOnly Then Continue For
    17. If dr0(iCol) Is DBNull.Value Then ' keine Änderung im Dialog -> alten Wert einsetzen
    18. dr0(iCol) = prevValues(iCol)
    19. Else ' Änderung im Dialog -> Eintrag in alle drvs
    20. For Each dr In drs
    21. dr(iCol) = dr0(iCol)
    22. Next
    23. End If
    24. Next
    25. bsDlg.EndEdit()
    26. 'bsDgv.ResetCurrentItem() 'den in bsDlg geänderten Datensatz auch in bsDgv neu einlesen. // dgv hat in dem Fall keine Bindingsource
    27. Else
    28. 'bsDgv.CancelEdit() // dgv hat in dem Fall keine Bindingsource
    29. End If
    30. End Function


    Visual Basic-Quellcode

    1. ''' <summary> Bereitet dr0 zur Weitergabe an den Dialog vor - dabei werden
    2. ''' nur Werte, die in jeder anderen DataRow aus List(Of DataRow) vorkommen eingetragen. </summary>
    3. Private Sub EditMultiPrepare(dr0 As DataRow, drs As List(Of DataRow))
    4. Dim columns = dr0.Table.Columns
    5. For iCol = 0 To columns.Count - 1
    6. If columns(iCol).ReadOnly Then Continue For
    7. For Each dr In drs
    8. If dr0(iCol).Equals(dr(iCol)) Then Continue For
    9. dr0(iCol) = Convert.DBNull
    10. Exit For
    11. Next
    12. Next
    13. End Sub



    aufruf hierüber: (Zeile 13)

    Visual Basic-Quellcode

    1. Private Sub MultiEdit()
    2. If Not checkMode() Then Return
    3. Dim selCells = dgv.storeDgvSelectedCells
    4. Dim lst As New List(Of DataRow)
    5. For Each selCell As DataGridViewCell In dgv.SelectedCells
    6. If Dts.TourGebiet.Where(Function(x) x.Gebiet = dgv.Columns(selCell.ColumnIndex).Name.LeftCut(".")).Count > 0 Then
    7. Dim rwGebiet = Dts.TourGebiet.First(Function(x) x.Gebiet = dgv.Columns(selCell.ColumnIndex).Name.LeftCut("."))
    8. Dim tourenplanID = convertInteger(dgv.Item($"{rwGebiet.Gebiet}.TourPlanID", selCell.RowIndex).Value)
    9. lst.Add(Dts.Tourenplan.First(Function(x) x.ID = tourenplanID))
    10. End If
    11. Next
    12. If lst.Count = 0 Then Return
    13. ShowMultiEditDialog(Of dlgTourenplanMulti)(dgv, lst)
    14. dgv.restoreDgvSelectedCells(selCells)
    15. For Each itm In selCells
    16. Dim iCol = dgv.Columns(convertInteger(itm.RightCut("."c)))
    17. Dim iRow = dgv.Rows(convertInteger(itm.LeftCut("."c)))
    18. Dim rwGebiet = Dts.TourGebiet.First(Function(x) x.Gebiet = iCol.Name.LeftCut("."))
    19. Dim rwTourenplan = Dts.Tourenplan.First(Function(x) x.ID = convertInteger(dgv.Item($"{rwGebiet.Gebiet}.TourPlanID", iRow.Index).Value))
    20. dgv.Item($"{rwGebiet.Gebiet}.Fahrer", iRow.Index).Value = rwTourenplan.MitarbeiterRow.expFullname
    21. dgv.Item($"{rwGebiet.Gebiet}.Fahrzeug", iRow.Index).Value = rwTourenplan.FahrzeugRow.Kennzeichen
    22. Next
    23. Dts.SaveDts()
    24. End Sub


    allerdings bekomme ich (nicht immer) folgende Exception:


    Aufruf:


    ich glaube, das hatten wir schonma - er konvertiert dann was in DBNull - wo es eigentlich nicht sein darf.
    Hast du eine Idee?
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup: