WPF Data Relation

  • WPF

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

    auch im NorthwindTester nicht.
    Zumindest bei mir - kann evtl. sein, dass ich den in dieser Hinsicht verschlimmbessert habe.
    Hast du einen Link auf einen Post, wo NorthwindTester übergeordnet verwiesene Properties anzeigt?

    habs gefunden, ja.
    Aber da wird auch nicht an eine BindingListCollection gebunden, sondern direkt an die DataTables.
    Hat den Vorteil, dass solche BindingPathes möglich sind, und den Nachteil, dass keine codeseitige Filterung möglich ist, und dass das SelectedItem nicht im Viewmodel verfügbar.

    Aber ich probier mal, über eine ListCollection zu binden, um die leidigen DataRowViews zu umgehen.

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

    HamburgerJungeJr schrieb:

    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.
    habe inzwischen noch paar Sachen probiert, und dadurch auch diese Problemstellung besser verstanden.
    Und - nö, denke nicht, dasses was besseres gibt als eine Combobox in einer Combobox. Und zwar mit einem ControlTemplate der inneren Combo, was sie als Textblock erscheinen lässt.
    einfach exakt so, wie ichs sage:

    XML-Quellcode

    1. <ComboBox ItemsSource="{Binding Path=TheDataset.Artikel}" DisplayMemberPath="Artikelname" IsSynchronizedWithCurrentItem="True">
    2. <Control.Template>
    3. <ControlTemplate TargetType="{x:Type ComboBox}">
    4. <TextBlock Text="{TemplateBinding Text}"/>
    5. </ControlTemplate>
    6. </Control.Template>
    7. </ComboBox>
    Ok. Ich hatte das so verstanden, das eine Combobox immer einen Togglebutton, Popup etc. benötigt.

    Ich versuche gerade die Schriftfarbe von der äußeren Combobox auf die innere zu übertragen.
    Wenn ich das so versuche, bekomme ich die Meldung in der Ausgabe

    Quellcode

    1. System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.ComboBoxItem', AncestorLevel='1''. BindingExpression:Path=Foreground; DataItem=null; target element is 'TextBlock' (Name=''); target property is 'Foreground' (type 'Brush')


    VB.NET-Quellcode

    1. <TextBlock Text="{TemplateBinding Text, Converter={StaticResource dateConverter}}" Foreground="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ComboBoxItem}}, Path=Foreground}"/>

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

    Ich habe die ChildTabe nun auch ohne Combobox angezeigt bekommen.

    VB.NET-Quellcode

    1. <TextBlock Text="{Binding Path=r_Zeiten_Anwender/aNachname}" />

    r_Zeiten_Anweder ist der Name der DataRelation.

    Ich kann die Daten aber immer noch nicht sortieren, da ich hierbei einen Fehler bekomme

    VB.NET-Quellcode

    1. ​_zeiten.SortDescriptions.Add(New SortDescription("r_Zeiten_Veranstaltungen/vDatum", ListSortDirection.Descending))


    Mit eine GroupDescription funktioniert das aber.
    Hat jemand eine Idee, wie ich die Daten aufgrund der Childtable sortieren kann.
    Inzwischen habe ich herausgefunden, dass es nicht möglich sein soll, nach Spalten zu sortieren, die sich nicht in der Tabelle befinden. Daher habe ich jetzt eine Hilfstabelle, die die entsprechenden Spalten beinhaltet. Mithilfe einer Klasse füge ich die verschiedenen Tabellen zusammen und gebe diese dann aus.

    Die Hilfsklasse:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Data
    2. Public Class JoinTable
    3. Private _sourceTable As DataTable
    4. Private _destinationTable As DataTable
    5. Private _fields As List(Of JoinField)
    6. Public Sub New(ByRef source As DataTable, ByVal destination As DataTable, ByVal fields As List(Of JoinField))
    7. _sourceTable = source
    8. _destinationTable = destination
    9. _fields = fields
    10. End Sub
    11. Public Function Join() As DataTable
    12. Dim newRow As DataRow
    13. Dim sourceColumn As Object
    14. For Each row As DataRow In _sourceTable.Rows
    15. newRow = _destinationTable.NewRow()
    16. For Each field As JoinField In _fields
    17. If field.Source.Table Is _sourceTable Then
    18. sourceColumn = row.Item(field.Source)
    19. Else
    20. sourceColumn = row.GetParentRow(field.Relation).Item(field.Source)
    21. End If
    22. newRow.Item(field.Destination) = sourceColumn
    23. Next
    24. _destinationTable.Rows.Add(newRow)
    25. Next
    26. Return _destinationTable
    27. End Function
    28. Public Class JoinField
    29. Private _source As DataColumn
    30. Private _destination As DataColumn
    31. Private _relation As String
    32. Public Property Source As DataColumn
    33. Get
    34. Return _source
    35. End Get
    36. Set(value As DataColumn)
    37. _source = value
    38. End Set
    39. End Property
    40. Public Property Destination As DataColumn
    41. Get
    42. Return _destination
    43. End Get
    44. Set(value As DataColumn)
    45. _destination = value
    46. End Set
    47. End Property
    48. Public Property Relation As String
    49. Get
    50. Return _relation
    51. End Get
    52. Set(value As String)
    53. _relation = value
    54. End Set
    55. End Property
    56. Public Sub New(ByVal source As DataColumn, ByVal destination As DataColumn, Optional ByVal relation As String = Nothing)
    57. _source = source
    58. _destination = destination
    59. _relation = relation
    60. End Sub
    61. End Class
    62. End Class


    Das ViewModel:
    Spoiler anzeigen

    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. Imports Technik_Veranstaltungen.JoinTable
    10. Public Class vmMain
    11. Inherits ViewModelBase
    12. Private _dbPfad As String
    13. Private WithEvents _veranstaltungen As BindingListCollectionView
    14. Private WithEvents _anwender As BindingListCollectionView
    15. Private WithEvents _zeiten As BindingListCollectionView
    16. Private WithEvents _verfügbar As BindingListCollectionView
    17. Private _joinFieldsZeiten As New List(Of JoinField)
    18. Private _joinFieldsVerfügbar As New List(Of JoinField)
    19. Private _joinTableZeiten As JoinTable
    20. Private _joinTableVerfügbar As JoinTable
    21. Public Property dsTechnikVeranstaltungen As New dsTechnikVeranstaltungen
    22. Public ReadOnly Property veranstaltungen() As ICollectionView
    23. Get
    24. Return _veranstaltungen
    25. End Get
    26. End Property
    27. Public ReadOnly Property anwender() As ICollectionView
    28. Get
    29. Return _anwender
    30. End Get
    31. End Property
    32. Public ReadOnly Property zeiten() As ICollectionView
    33. Get
    34. Return _zeiten
    35. End Get
    36. End Property
    37. Public ReadOnly Property verfügbar() As ICollectionView
    38. Get
    39. Return _verfügbar
    40. End Get
    41. End Property
    42. Public Property ReLoad As New RelayCommand( _
    43. Sub()
    44. End Sub)
    45. Public Property NewVeranstaltung As New RelayCommand( _
    46. Sub()
    47. Dim row As dtVeranstaltungenRow = dsTechnikVeranstaltungen.dtVeranstaltungen.NewdtVeranstaltungenRow
    48. dsTechnikVeranstaltungen.dtVeranstaltungen.AdddtVeranstaltungenRow(row)
    49. _veranstaltungen.Refresh()
    50. _veranstaltungen.MoveCurrentToLast()
    51. End Sub)
    52. Public Property Save As New RelayCommand( _
    53. Sub()
    54. If dsTechnikVeranstaltungen.HasChanges Then
    55. End If
    56. End Sub)
    57. Public Sub New()
    58. _dbPfad = My.Settings.Datenbank
    59. If Not MyBase.IsInDesignMode Then
    60. load()
    61. join()
    62. setSortDescriptions()
    63. End If
    64. End Sub
    65. Private Sub load()
    66. loadFromDB("SELECT * FROM Veranstaltungen", dsTechnikVeranstaltungen.dtVeranstaltungen)
    67. loadFromDB("SELECT * FROM Anwender", dsTechnikVeranstaltungen.dtAnwender)
    68. loadFromDB("SELECT Zeiten.* FROM Veranstaltungen RIGHT JOIN (Zeiten LEFT JOIN Anwender ON Zeiten.zAnwender = Anwender.aId) ON Veranstaltungen.vId = Zeiten.zVeranstaltung ORDER BY Anwender.aNachname, Anwender.aVorname;", dsTechnikVeranstaltungen.dtZeiten)
    69. loadFromDB("SELECT Verfügbar.* FROM (Verfügbar LEFT JOIN Veranstaltungen ON Verfügbar.vfVeranstaltung = Veranstaltungen.vId) LEFT JOIN Anwender ON Verfügbar.vfAnwender = Anwender.aId ORDER BY Veranstaltungen.vDatum DESC , Anwender.aNachname, Anwender.aVorname;", dsTechnikVeranstaltungen.dtVerfügbar)
    70. End Sub
    71. Private Sub loadFromDB(ByVal command As String, ByVal table As DataTable)
    72. Dim con As New OleDbConnection
    73. Dim cmd As New OleDbCommand
    74. con.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & _dbPfad & "; Persist Security Info=True;"
    75. cmd.Connection = con
    76. Try
    77. con.Open()
    78. cmd.CommandText = command
    79. Dim reader As OleDbDataReader = cmd.ExecuteReader
    80. table.Load(reader)
    81. reader.Close()
    82. con.Close()
    83. Catch ex As Exception
    84. MessageBox.Show(ex.Message)
    85. End Try
    86. End Sub
    87. Private Sub setSortDescriptions()
    88. 'Veranstaltungen
    89. _veranstaltungen = DirectCast(CollectionViewSource.GetDefaultView(dsTechnikVeranstaltungen.dtVeranstaltungen), BindingListCollectionView)
    90. _veranstaltungen.SortDescriptions.Add(New SortDescription("vDatum", ListSortDirection.Descending))
    91. _veranstaltungen.MoveCurrentToFirst()
    92. 'Anwender
    93. _anwender = DirectCast(CollectionViewSource.GetDefaultView(dsTechnikVeranstaltungen.dtAnwender), BindingListCollectionView)
    94. _anwender.SortDescriptions.Add(New SortDescription("aNachname", ListSortDirection.Ascending))
    95. _anwender.SortDescriptions.Add(New SortDescription("aVorname", ListSortDirection.Ascending))
    96. _anwender.MoveCurrentToFirst()
    97. 'Zeiten
    98. _zeiten = DirectCast(CollectionViewSource.GetDefaultView(_joinTableZeiten.Join()), BindingListCollectionView)
    99. _zeiten.SortDescriptions.Add(New SortDescription("vDatum", ListSortDirection.Descending))
    100. _zeiten.SortDescriptions.Add(New SortDescription("aNachname", ListSortDirection.Ascending))
    101. _zeiten.SortDescriptions.Add(New SortDescription("aVorname", ListSortDirection.Ascending))
    102. _zeiten.MoveCurrentToFirst()
    103. 'Verfügbar
    104. _verfügbar = DirectCast(CollectionViewSource.GetDefaultView(_joinTableVerfügbar.Join()), BindingListCollectionView)
    105. _verfügbar.SortDescriptions.Add(New SortDescription("vDatum", ListSortDirection.Descending))
    106. _verfügbar.SortDescriptions.Add(New SortDescription("aNachname", ListSortDirection.Ascending))
    107. _verfügbar.SortDescriptions.Add(New SortDescription("aVorname", ListSortDirection.Ascending))
    108. _verfügbar.MoveCurrentToFirst()
    109. End Sub
    110. Private Sub join()
    111. With dsTechnikVeranstaltungen
    112. 'Zeiten
    113. _joinFieldsZeiten.Add(New JoinField(.dtZeiten.zIdColumn, .dtJoinZeiten.zIdColumn))
    114. _joinFieldsZeiten.Add(New JoinField(.dtVeranstaltungen.vDatumColumn, .dtJoinZeiten.vDatumColumn, "r_Veranstaltungen_Zeiten"))
    115. _joinFieldsZeiten.Add(New JoinField(.dtVeranstaltungen.vNameColumn, .dtJoinZeiten.vNameColumn, "r_Veranstaltungen_Zeiten"))
    116. _joinFieldsZeiten.Add(New JoinField(.dtAnwender.aNachnameColumn, .dtJoinZeiten.aNachnameColumn, "r_Anwender_Zeiten"))
    117. _joinFieldsZeiten.Add(New JoinField(.dtAnwender.aVornameColumn, .dtJoinZeiten.aVornameColumn, "r_Anwender_Zeiten"))
    118. _joinTableZeiten = New JoinTable(.dtZeiten, .dtJoinZeiten, _joinFieldsZeiten)
    119. 'Verfügbar
    120. _joinFieldsVerfügbar.Add(New JoinField(.dtVerfügbar.vfIdColumn, .dtJoinVerfügbar.vfIdColumn))
    121. _joinFieldsVerfügbar.Add(New JoinField(.dtVeranstaltungen.vDatumColumn, .dtJoinVerfügbar.vDatumColumn, "r_Veranstaltungen_Verfügbar"))
    122. _joinFieldsVerfügbar.Add(New JoinField(.dtAnwender.aNachnameColumn, .dtJoinVerfügbar.aNachnameColumn, "r_Anwender_Verfügbar"))
    123. _joinFieldsVerfügbar.Add(New JoinField(.dtAnwender.aVornameColumn, .dtJoinVerfügbar.aVornameColumn, "r_Anwender_Verfügbar"))
    124. _joinTableVerfügbar = New JoinTable(.dtVerfügbar, .dtJoinVerfügbar, _joinFieldsVerfügbar)
    125. End With
    126. End Sub
    127. End Class


    Das XAML:
    Spoiler anzeigen

    Quellcode

    1. <Grid x:Name="g_Zeiten" DataContext="{Binding zeiten}">
    2. <Grid.ColumnDefinitions>
    3. <ColumnDefinition Width="95" />
    4. <ColumnDefinition Width="100" />
    5. <ColumnDefinition Width="18" />
    6. <ColumnDefinition Width="65" />
    7. <ColumnDefinition Width="14" />
    8. <ColumnDefinition Width="65" />
    9. <ColumnDefinition Width="14" />
    10. <ColumnDefinition Width="*" />
    11. </Grid.ColumnDefinitions>
    12. <Grid.RowDefinitions>
    13. <RowDefinition Height="45" />
    14. <RowDefinition Height="22" />
    15. <RowDefinition Height="15" />
    16. <RowDefinition Height="22" />
    17. <RowDefinition Height="5" />
    18. <RowDefinition Height="22" />
    19. <RowDefinition Height="5" />
    20. <RowDefinition Height="22" />
    21. <RowDefinition Height="5" />
    22. <RowDefinition Height="22" />
    23. <RowDefinition Height="5" />
    24. <RowDefinition Height="22" />
    25. <RowDefinition Height="5" />
    26. <RowDefinition Height="167" />
    27. <RowDefinition Height="*" />
    28. </Grid.RowDefinitions>
    29. <ComboBox x:Name="c_zAuswahl" Grid.Column="1" Grid.Row="1" Style="{StaticResource comboboxStyle}" Grid.ColumnSpan="6" IsTabStop="False" IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding}">
    30. <ComboBox.ItemTemplate>
    31. <DataTemplate>
    32. <StackPanel Orientation="Horizontal">
    33. <TextBlock Text="{Binding Path=vDatum, Converter={StaticResource dateConverter}}" />
    34. <TextBlock Text=" / " />
    35. <TextBlock Text="{Binding Path=aNachname}" />
    36. <TextBlock Text=", " />
    37. <TextBlock Text="{Binding Path=aVorname}" />
    38. </StackPanel>
    39. </DataTemplate>
    40. </ComboBox.ItemTemplate>
    41. </ComboBox>
    42. <Label x:Name="l_zName" Content="Name:" Grid.Column="0" Grid.Row="3" Style="{StaticResource labelStyle}" />
    43. <ComboBox x:Name="c_zName" Grid.Column="1" Grid.Row="3" Style="{StaticResource comboboxStyle}" Grid.ColumnSpan="6" ItemsSource="{Binding Path=anwender, Source={StaticResource vmMain}}" SelectedValue="{Binding Path=r_ZeitenJoin/zAnwender}" SelectedValuePath="aId">
    44. <ComboBox.ItemTemplate>
    45. <DataTemplate>
    46. <StackPanel Orientation="Horizontal">
    47. <TextBlock Text="{Binding Path=aNachname}" />
    48. <TextBlock Text=", " />
    49. <TextBlock Text="{Binding Path=aVorname}" />
    50. </StackPanel>
    51. </DataTemplate>
    52. </ComboBox.ItemTemplate>
    53. </ComboBox>
    54. <Label x:Name="l_zVeranstaltung" Content="Veranstaltung:" Grid.Column="0" Grid.Row="5" Style="{StaticResource labelStyle}" />
    55. <ComboBox x:Name="c_zvAuswahl" Grid.Column="1" Grid.Row="5" Style="{StaticResource comboboxStyle}" Grid.ColumnSpan="6" IsTabStop="False" ItemsSource="{Binding Path=veranstaltungen, Source={StaticResource vmMain}}" SelectedValue="{Binding Path=r_ZeitenJoin/zVeranstaltung}" SelectedValuePath="vId">
    56. <ComboBox.ItemTemplate>
    57. <DataTemplate>
    58. <StackPanel Orientation="Horizontal">
    59. <TextBlock Text="{Binding Path=vDatum, StringFormat=dd.MM.yyyy}" />
    60. <TextBlock Text=" / " />
    61. <TextBlock Text="{Binding Path=vName}" />
    62. </StackPanel>
    63. </DataTemplate>
    64. </ComboBox.ItemTemplate>
    65. </ComboBox>
    66. <Label x:Name="l_zBeginn" Content="Beginn:" Grid.Column="0" Grid.Row="7" Style="{StaticResource labelStyle}" />
    67. <custom:MaskedTextBox x:Name="t_zBeginn" Grid.Column="1" Grid.Row="7" Style="{StaticResource textboxStyle}" Mask="90:00" IgnoreSpace="True" Text="{Binding Path=r_ZeitenJoin/zAnkunft, StringFormat=HH:mm}" />
    68. <Button x:Name="s_zBeginn" Content="Beginn Jetzt" Grid.Column="3" Grid.Row="7" Style="{StaticResource buttonStyle}" Grid.ColumnSpan="2"/>
    69. <Label x:Name="l_zEnde" Content="Ende:" Grid.Column="0" Grid.Row="9" Style="{StaticResource labelStyle}"/>
    70. <custom:MaskedTextBox x:Name="t_zEnde" Grid.Column="1" Grid.Row="9" Style="{StaticResource textboxStyle}" Mask="90:00" IgnoreSpace="True" Text="{Binding Path=r_ZeitenJoin/zEnde, StringFormat=HH:mm}" />
    71. <Button x:Name="s_zEnde" Content="Ende Jetzt" Grid.Column="3" Grid.Row="9" Style="{StaticResource buttonStyle}" Grid.ColumnSpan="2"/>
    72. <Label x:Name="l_zDauer" Content="Dauer:" Grid.Column="0" Grid.Row="11" Style="{StaticResource labelStyle}"/>
    73. <custom:MaskedTextBox x:Name="t_zDauer" Grid.Column="1" Grid.Row="11" Style="{StaticResource textboxStyle}" Mask="90:00" IgnoreSpace="True" IsReadOnly="True">
    74. <MultiBinding Converter="{StaticResource timeSpanConverter}">
    75. <Binding Path="r_ZeitenJoin/zAnkunft"/>
    76. <Binding Path="r_ZeitenJoin/zEnde"/>
    77. </MultiBinding>
    78. </custom:MaskedTextBox>
    79. </Grid>


    Bin für Verbesserungen natürlich weiterhin offen. ;)

    HamburgerJungeJr
    Bilder
    • Dataset.JPG

      119,69 kB, 1.154×606, 104 mal angesehen
    mir scheint, du hast die berechnete Spalte neu erfunden ;)
    Also Werte übergeordneter DataTables kann man als ReadOnly-Spalten in der untergeordneten DataTable anzeigen/anlegen.
    Und danach kann man dann natürlich auch sortieren.
    berechnete Spalten kann man direkt im Dataset-Designer hinbasteln.

    gugge DataExpressions



    (über unnötige Prefixe, ungeeignete und uneinheitliche Plural-Flexierung, uneinheitliche Schlüsselspalten-Benamung und sowas hab ich bestimmt mit dir schon drüber diskutiert, oder?)

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