WPF Data Relation

  • WPF

Es gibt 35 Antworten in diesem Thema. Der letzte Beitrag () ist von HamburgerJungeJr.

    WPF Data Relation

    Moin,

    wie kann ich in WPF auf die Daten von einer Data-Relation im Dataset zugreifen?
    In WinForms hatte ich dazu die BindingSource, die mir die Relation ausgab.

    Außerdem bekomme ich immer den Fehler, dass es ein Problem mit Foreign-Key oder Unique gibt. Es sind aber nur die ID-Spalten auf Unique gesetzt und es gibt auch alle Ids in den Tabellen.


    Gruß
    HamburgerJungeJr
    sind 2 Projekte - das Northwind-sample geht - es geht sogar doch in gewisserweise mit Zusammenstöpseln.
    Im Readme steht auch noch ein Problem wassich bisher noch nicht gelöst hab.
    Dateien

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ErfinderDesRades“ ()

    jetzt hab ichs mittm Artikel-Filter gelöst, der in Category_CurrentChanged immer nachgeführt wird.
    Ist doch nicht dolle, die Filter-Option, die ich eiglich gedacht hätte, wird von BindingListCollectionView nicht unterstützt.

    also in WinForms mitte BindingSources ist das schöner gelöst :(
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.IO
    2. Imports System.Data
    3. Imports NorthwindTester.NorthWindDts
    4. Imports Microsoft.VisualBasic
    5. Public Class MainModel : Inherits MainModelBase(Of MainModel)
    6. Private _DataFile As New FileInfo("..\..\Northwind.Xml")
    7. Public Property TheDataset As New NorthWindDts
    8. Public Property ReLoad As New RelayCommand( _
    9. Sub()
    10. TheDataset.Clear()
    11. TheDataset.ReadXml(_DataFile.FullName)
    12. TheDataset.AcceptChanges()
    13. End Sub, _
    14. Function() TheDataset.HasChanges)
    15. Public Property Save As New RelayCommand( _
    16. Sub()
    17. TheDataset.WriteXml(_DataFile.FullName)
    18. TheDataset.AcceptChanges()
    19. System.Media.SystemSounds.Asterisk.Play()
    20. End Sub, _
    21. Function() TheDataset.HasChanges)
    22. Private WithEvents _Categories As BindingListCollectionView
    23. Public ReadOnly Property Categories() As BindingListCollectionView
    24. Get
    25. Return _Categories.CreateLazy(Function() DirectCast(CollectionViewSource.GetDefaultView(TheDataset.Kategorien), BindingListCollectionView))
    26. End Get
    27. End Property
    28. Private WithEvents _Articles As BindingListCollectionView
    29. Public ReadOnly Property Articles() As BindingListCollectionView
    30. Get
    31. Return _Articles.CreateLazy(Function() DirectCast(CollectionViewSource.GetDefaultView(TheDataset.Artikel), BindingListCollectionView))
    32. End Get
    33. End Property
    34. Public Sub New()
    35. If MyBase.IsProvisional Then Return
    36. ReLoad.Execute(Nothing)
    37. End Sub
    38. Private Sub _Categories_CurrentChanged(sender As Object, e As System.EventArgs) Handles _Categories.CurrentChanged
    39. Dim itm = _Categories.CurrentItem
    40. Dbg("Category:", If(itm Is Nothing, "#null#", DirectCast(DirectCast(itm, DataRowView).Row, KategorienRow).Kategoriename))
    41. If itm Is Nothing Then Return
    42. Dim rw = DirectCast(DirectCast(itm, DataRowView).Row, KategorienRow)
    43. Articles.CustomFilter = "KategorieID=" & rw.KategorieID
    44. 'Articles.Filter = Function(o) DirectCast(DirectCast(o, DataRowView).Row, ArtikelRow).KategorienRow Is rw 'wird nicht unterstützt
    45. End Sub
    46. End Class
    Ich habe die Relations hinbekommen, stehe nur gerade vor dem Problem, wie ich Daten aus einer Anderen Tabelle in einer Combobox anzeigen lassen kann. Ich habe es mit einer weiteren Combobox im DataTemplate hinbekommen, es soll aber nur der Text erscheinen und nicht die Combobox.

    VB.NET-Quellcode

    1. <ComboBox.ItemTemplate>
    2. <DataTemplate>
    3. <StackPanel Orientation="Horizontal">
    4. <!--<ComboBox ItemsSource="{Binding Source={StaticResource vmMain}, Path=veranstaltungen}" DisplayMemberPath="vDatum" SelectedValuePath="vId" SelectedValue="{Binding Path=zVeranstaltung}" IsReadOnly="True"/>-->
    5. <TextBlock Text="{Binding Path=veranstaltungen/vDatum, Source={StaticResource vmMain}, StringFormat=dd.MM.yyyy}" />
    6. <TextBlock Text=" / " />
    7. <TextBlock Text="{Binding Path=anwender/aNachname, Source={StaticResource vmMain}}" />
    8. <TextBlock Text=", " />
    9. <TextBlock Text="{Binding Path=anwender/aVorname, Source={StaticResource vmMain}}" />
    10. </StackPanel>
    11. </DataTemplate>
    12. </ComboBox.ItemTemplate>

    Im Moment werden mir nur die Daten des ersten Datensatzes aus der verknüpften Tabelle angezeigt.
    ja, das ist das Elend, dass man für typsierte Datasetklassen keinen Datentyp im DataTemplate angeben kann. Damit entfällt BindingPicking, und man kann sich dumm und dämlich probieren.
    probierma

    XML-Quellcode

    1. <TextBlock Text="{Binding Path=veranstaltungenRow.vDatum}" />

    ansonsten Bild vom Dataset posten
    ViemModel:

    VB.NET-Quellcode

    1. ​Imports System.IO
    2. Imports System.Data
    3. Imports Technik_Veranstaltungen.dsTechnikVeranstaltungen
    4. Imports Microsoft.VisualBasic
    5. Imports Technik_Veranstaltungen.ViewModel
    6. Imports System.Data.OleDb
    7. Imports System.ComponentModel
    8. Imports Technik_Veranstaltungen.ObjectX
    9. Public Class vmMain
    10. Inherits ViewModelBase
    11. Private dbPfad As String
    12. Private WithEvents _veranstaltungen As ICollectionView
    13. Private WithEvents _anwender As ICollectionView
    14. Private WithEvents _zeiten As ICollectionView
    15. Private WithEvents _verfügbar As ICollectionView
    16. Public Property dsTechnikVeranstaltungen As New dsTechnikVeranstaltungen
    17. Public ReadOnly Property veranstaltungen() As ICollectionView
    18. Get
    19. Return _veranstaltungen.CreateLazy(Function() CollectionViewSource.GetDefaultView(dsTechnikVeranstaltungen.dtVeranstaltungen))
    20. End Get
    21. End Property
    22. Public ReadOnly Property anwender() As ICollectionView
    23. Get
    24. Return _anwender.CreateLazy(Function() CollectionViewSource.GetDefaultView(dsTechnikVeranstaltungen.dtAnwender))
    25. End Get
    26. End Property
    27. Public ReadOnly Property zeiten() As ICollectionView
    28. Get
    29. Return _zeiten.CreateLazy(Function() CollectionViewSource.GetDefaultView(dsTechnikVeranstaltungen.dtZeiten))
    30. End Get
    31. End Property
    32. Public ReadOnly Property verfügbar() As ICollectionView
    33. Get
    34. Return _verfügbar.CreateLazy(Function() CollectionViewSource.GetDefaultView(dsTechnikVeranstaltungen.dtVerfügbar))
    35. End Get
    36. End Property
    37. Public Property ReLoad As New RelayCommand( _
    38. Sub()
    39. dbPfad = My.Settings.Datenbank
    40. load()
    41. End Sub)
    42. Public Sub New()
    43. dbPfad = My.Settings.Datenbank
    44. If Not MyBase.IsInDesignMode Then
    45. load()
    46. End If
    47. End Sub
    48. Private Sub load()
    49. loadFromDB("SELECT * FROM Veranstaltungen ORDER BY vDatum DESC", dsTechnikVeranstaltungen.dtVeranstaltungen)
    50. loadFromDB("SELECT * FROM Anwender ORDER BY aNachname, aVorname ASC", dsTechnikVeranstaltungen.dtAnwender)
    51. loadFromDB("SELECT Zeiten.* FROM Veranstaltungen RIGHT JOIN (Zeiten LEFT JOIN Anwender ON Zeiten.zAnwender = Anwender.aId) ON Veranstaltungen.vId = Zeiten.zVeranstaltung ORDER BY Veranstaltungen.vDatum DESC , Anwender.aNachname, Anwender.aVorname;", dsTechnikVeranstaltungen.dtZeiten)
    52. End Sub
    53. Private Sub loadFromDB(ByVal command As String, ByVal table As DataTable)
    54. Dim con As New OleDbConnection
    55. Dim cmd As New OleDbCommand
    56. con.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & dbPfad & "; Persist Security Info=True;"
    57. cmd.Connection = con
    58. Try
    59. con.Open()
    60. cmd.CommandText = command
    61. Dim reader As OleDbDataReader = cmd.ExecuteReader
    62. table.Load(reader)
    63. reader.Close()
    64. con.Close()
    65. Catch ex As Exception
    66. MessageBox.Show(ex.Message)
    67. End Try
    68. End Sub
    69. End Class
    Bilder
    • Dataset.JPG

      44,12 kB, 640×323, 65 mal angesehen
    Ne war vielleicht etwas merkwürdig ausgedrückt.

    Ich habe eine Combobox zur Auswahl der Arbeitszeiten (Tabelle dtZeiten). In dieser Combobox möchte ich aus der Tabelle dtVeranstaltungen die Spalte vDatum und aus der Tabelle dtAnwender die Spalten aVorname und aNachname anzeigen.

    Wenn ich im DataTemplate dieser Combobox nun einen TextBlock zur Anzeige der verknüpften Spalte benutze, wird mir immer der gleicher Datensatz, der erste der verknüpften Tabellen, für alle Datensätze der Tabelle dtZeiten angezeigt. Nehme ich nun statt des TextBlock eine Combobox funktioniert alles, ich habe nur eine Combobox in einer Combobox. Gibt es einen anderen Weg, die verknüpften Spalten anzuzeigen, als ein Style für die Combobox zu erstellen, bei dem nur ein TextBlock angezeigt wird?

    Hoffe es ist nun verständlicher.
    also du willst eine Combo mit 4 Spalten?

    XML-Quellcode

    1. <ComboBox.ItemTemplate>
    2. <DataTemplate>
    3. <StackPanel Orientation="Horizontal">
    4. <TextBlock Text="{Binding Path=zAnkunft}" /> <!--wenn diese Spalte nicht geht, stimmt was mitte ItemsSource nicht-->
    5. <TextBlock Text="{Binding Path=Row.dtAnwenderRow.aVorname}" /> <!-- bei DB-Benamungen: lass so Prefixe besser weg - die bringen nix ausser Hirn-Koliken -->
    6. </StackPanel>
    7. </DataTemplate>
    8. </ComboBox.ItemTemplate>
    sind nur 2 Spalten, und ist nur ein Versuch. Bin unsicher, ob man an die DataRowview.Row-Property binden kann.
    Die erste Zeile funktioniert, die Zweite verstehe ich nicht. Wie komme ich jetzt plötzlich an eine Row?
    Zu der Benennung: Ich habe mir das irgendwann mal angewöhnt und bei kleineren Datenbanken finde ich das persönlich ganz hilfreich, wenn ich weiß, aus welcher Tabelle die Spalte nun stammt. Brei größeren gebe ich dir Recht wird das unübersichtlich.
    funktioniert sie denn, die 2. Spalte?

    Zur Benennung: Im Code sind überhaupt keine Tabellen-unabhängigen Zugriffe auf Spalten möglich. Daher weiß man immer, aus welcher Tabelle eine Spalte kommt.

    Auch der dt-Prefix bringt nix, denn in einem Dataset kann ja garnix anneres sein als DataTables.
    Die zweite Spalte zeigt mir gar nix an. In deinem Beispiel mit dem _DatasetTester funktioniert das ganze ja im DataGrid wieso nicht bei mir in der Combobox??? ?(

    Über die Bennenung kann man bestimmt lange diskutieren...
    In WinForms hatte ich mir angewöhnt allen Steuerelementen einen passenden Präfix zu verpassen, daher auch im Dataset. Die Spaltenbennenung habe ich hauptsächlich für SQL-Abfragen mit Join-Ausdrücken um zum einen die Herkunft klar erkennbar zu haben, zum Anderen, um mir etwas Schreibarbeit mit den sonst benötigten Tabellen-Präfixen zu ersparen. ^^

    Ist ja aber eigentlich auch egal. Mein Problem ist ein anderes, das ich hoffentlich bald gelöst bekomme.