Werte aus DataGrid werden nicht in die Collection übernommen

  • WPF

Es gibt 6 Antworten in diesem Thema. Der letzte Beitrag () ist von eichseinet.

    Werte aus DataGrid werden nicht in die Collection übernommen

    Hallo!

    Nachdem ich mein Lernprojekt jetzt fast fertig hatte, fiel mir vorhin ein ganz enormer Fehler auf. Werte, die manuell im DataGrid geändert werden, gelangen nicht in die Collection. Der neue Wert bleibt nur solange in der Zelle stehen, bis ich z.B. sortiere. Ändert sich ein Wert über den Code in der Collection, dann zeigt das Grid den neuen Wert an.
    Die Daten liegen in einer ObservableCollection, die an eine ICollectionView gebunden ist. Diese wiederum ist dann an das DataGrid gebunden.

    XAML:

    Spoiler anzeigen

    XML-Quellcode

    1. <Window x:Class="MainWindow"
    2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    4. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    5. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    6. xmlns:local="clr-namespace:Databinding_mit_View02"
    7. xmlns:Converter="clr-namespace:Databinding_mit_View02.Converter"
    8. mc:Ignorable="d"
    9. Title="MainWindow" Height="600" Width="800">
    10. <Grid>
    11. <TabControl>
    12. <TabItem x:Name="DataGrid2_Tab" Header="DataGrid2">
    13. <TabItem.Resources>
    14. <!--Vorlage fürs ganze DataGrid-->
    15. <Style x:Key="GridStyle_Key" TargetType="{x:Type DataGrid}">
    16. <Setter Property="ColumnHeaderStyle" Value="{DynamicResource SpaltenStyle_Key}"/>
    17. </Style>
    18. <!--Vorlage für die Spalten-->
    19. <Style x:Key="SpaltenStyle_Key" TargetType="DataGridColumnHeader">
    20. <Setter Property="Height" Value="30"/>
    21. <Setter Property="FontSize" Value="16"/>
    22. <Style.Triggers>
    23. <Trigger Property="IsMouseOver" Value="true">
    24. <Setter Property="ToolTip" Value="Sortierbar, weil im XAML der Spalte ein SortMemberPath zugewiesen ist"/>
    25. <Setter Property="ToolTipService.ShowDuration" Value="60000"/>
    26. </Trigger>
    27. </Style.Triggers>
    28. </Style>
    29. <Converter:TextinFarbeConverter x:Key="TextinFarbeConverter_Key"/>
    30. </TabItem.Resources>
    31. <Grid>
    32. <Grid.RowDefinitions>
    33. <RowDefinition/>
    34. <RowDefinition Height="120"/>
    35. </Grid.RowDefinitions>
    36. <DataGrid x:Name="Grid2" ItemsSource="{Binding Aufnahmen_View, Mode=TwoWay}" AutoGenerateColumns="False" Style="{DynamicResource GridStyle_Key}" SelectionUnit="CellOrRowHeader">
    37. <DataGrid.Columns>
    38. <DataGridTemplateColumn Header="löschen">
    39. <DataGridTemplateColumn.HeaderStyle>
    40. <Style TargetType="DataGridColumnHeader">
    41. <Setter Property="Height" Value="30"/>
    42. <Setter Property="FontSize" Value="16"/>
    43. <Style.Triggers>
    44. <Trigger Property="IsMouseOver" Value="true">
    45. <Setter Property="ToolTip" Value="Style direkt der Spalte zugewiesen"/>
    46. <Setter Property="ToolTipService.ShowDuration" Value="60000"/>
    47. </Trigger>
    48. </Style.Triggers>
    49. </Style>
    50. </DataGridTemplateColumn.HeaderStyle>
    51. <DataGridTemplateColumn.CellTemplate>
    52. <DataTemplate>
    53. <Button Content="löschen" CommandParameter="{Binding Path=ID}" Click="Button_Click_1" ToolTip="löscht diese Zeile aus der Collection, auch wenn sortiert wurde!" ToolTipService.ShowDuration="60000"/>
    54. </DataTemplate>
    55. </DataGridTemplateColumn.CellTemplate>
    56. </DataGridTemplateColumn>
    57. <DataGridTemplateColumn Header="ID" SortMemberPath="ID" IsReadOnly="True">
    58. <DataGridTemplateColumn.CellTemplate>
    59. <DataTemplate>
    60. <TextBox Text="{Binding ID}"/>
    61. </DataTemplate>
    62. </DataGridTemplateColumn.CellTemplate>
    63. </DataGridTemplateColumn>
    64. <DataGridTemplateColumn Header="Ordner" SortMemberPath="Ordner" Width="200">
    65. <DataGridTemplateColumn.CellTemplate>
    66. <DataTemplate>
    67. <TextBox Text="{Binding Ordner}" BorderThickness="0" Background="Aquamarine"/>
    68. </DataTemplate>
    69. </DataGridTemplateColumn.CellTemplate>
    70. </DataGridTemplateColumn>
    71. <DataGridTemplateColumn Header="Dateiname" SortMemberPath="Dateiname">
    72. <DataGridTemplateColumn.CellTemplate>
    73. <DataTemplate>
    74. <TextBox Text="{Binding Dateiname}"/>
    75. </DataTemplate>
    76. </DataGridTemplateColumn.CellTemplate>
    77. </DataGridTemplateColumn>
    78. <DataGridTemplateColumn Header="Datum" SortMemberPath="Datum">
    79. <DataGridTemplateColumn.CellTemplate>
    80. <DataTemplate>
    81. <TextBox Text="{Binding Datum, StringFormat={}dd.MM.yyyy}"/>
    82. </DataTemplate>
    83. </DataGridTemplateColumn.CellTemplate>
    84. </DataGridTemplateColumn>
    85. <!--SortMemberPath muss auf das gleiche Property wie der Text eingestellt sein, um über den Spaltenkopf sortieren zu können-->
    86. <DataGridTemplateColumn Header="Größe" SortMemberPath="Groesse">
    87. <DataGridTemplateColumn.CellTemplate>
    88. <DataTemplate>
    89. <!--durch ConverterCulture zeigt die Zelle ein Komma statt einen Punkt in den Zahlen, Stringformat sorgt dann nur immer für eine Nachkommastelle-->
    90. <TextBox Text="{Binding Groesse, Mode=TwoWay, ConverterCulture='de-DE', StringFormat=0.0}" TextAlignment="Right" Background="{Binding Path=Hintergrund_Groesse, Converter={StaticResource TextinFarbeConverter_Key}}"/>
    91. </DataTemplate>
    92. </DataGridTemplateColumn.CellTemplate>
    93. </DataGridTemplateColumn>
    94. <DataGridTemplateColumn Header="Hintergrund Groesse">
    95. <DataGridTemplateColumn.CellTemplate>
    96. <DataTemplate>
    97. <TextBox Text="{Binding Hintergrund_Groesse}"/>
    98. </DataTemplate>
    99. </DataGridTemplateColumn.CellTemplate>
    100. </DataGridTemplateColumn>
    101. </DataGrid.Columns>
    102. </DataGrid>


    Code (auszugsweise):
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private _aufnahmen_coll As ObservableCollection(Of Aufnahmen)
    2. Public Property Aufnahmen_Coll() As ObservableCollection(Of Aufnahmen)
    3. Get
    4. Return _aufnahmen_coll
    5. End Get
    6. Set(ByVal value As ObservableCollection(Of Aufnahmen))
    7. _aufnahmen_coll = value
    8. raisepropertychanged()
    9. End Set
    10. End Property
    11. Private _aufnahmen_view As ICollectionView
    12. Public Property Aufnahmen_View() As ICollectionView
    13. Get
    14. Return _aufnahmen_view
    15. End Get
    16. Set(ByVal value As ICollectionView)
    17. _aufnahmen_view = value
    18. raisepropertychanged()
    19. End Set
    20. End Property
    21. Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
    22. Aufnahmen_Coll = New ObservableCollection(Of Aufnahmen)
    23. Aufnahmen_Coll.Add(New Aufnahmen("C:\temp0", "Dings.txt", "24.03.2019", "234,5", 0, "rot"))
    24. Aufnahmen_Coll.Add(New Aufnahmen("C:\temp3", "Uings.txt", "24.03.2019", "111", 1, ""))
    25. Aufnahmen_Coll.Add(New Aufnahmen("C:\temp1", "aings.txt", "24.03.2019", "334,7", 2, "rot"))
    26. Aufnahmen_Coll.Add(New Aufnahmen("C:\temp2", "Kings.txt", "24.03.2019", "96,6", 3, ""))
    27. Aufnahmen_View = CollectionViewSource.GetDefaultView(Aufnahmen_Coll)
    28. Aufnahmen_View.Filter = AddressOf Filterfunktion_DG2
    29. End Sub
    30. Me.DataContext = Me



    Klasse:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.ComponentModel
    2. Imports System.Runtime.CompilerServices
    3. Public Class Aufnahmen
    4. Implements INotifyPropertyChanged
    5. Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
    6. Private Sub raisepropertychanged(<CallerMemberName> Optional ByVal prop As String = "") 'wird bei Änderung in den Propertys aufgerufen
    7. RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(prop))
    8. End Sub
    9. Public Sub New() 'für Speicherfunktion nötig
    10. End Sub
    11. Public Sub New(ordner As String, dateiname As String, datum As Date, groesse As Single)
    12. Me.Ordner = ordner : Me.Dateiname = dateiname : Me.Datum = datum : Me.Groesse = groesse
    13. End Sub
    14. Public Sub New(ordner As String, dateiname As String, datum As Date, groesse As Single, id As Integer)
    15. Me.Ordner = ordner : Me.Dateiname = dateiname : Me.Datum = datum : Me.Groesse = groesse : Me.ID = id
    16. End Sub
    17. Public Sub New(ordner As String, dateiname As String, datum As Date, groesse As Single, id As Integer, hintergrund_groesse As String)
    18. Me.Ordner = ordner : Me.Dateiname = dateiname : Me.Datum = datum : Me.Groesse = groesse : Me.ID = id : Me.Hintergrund_Groesse = hintergrund_groesse
    19. End Sub
    20. Private _ordner As String
    21. Public Property Ordner() As String
    22. Get
    23. Return _ordner
    24. End Get
    25. Set(ByVal value As String)
    26. _ordner = value
    27. raisepropertychanged()
    28. End Set
    29. End Property
    30. Private _dateiname As String
    31. Public Property Dateiname() As String
    32. Get
    33. Return _dateiname
    34. End Get
    35. Set(ByVal value As String)
    36. _dateiname = value
    37. raisepropertychanged()
    38. End Set
    39. End Property
    40. Private _datum As Date
    41. Public Property Datum() As Date
    42. Get
    43. Return _datum
    44. End Get
    45. Set(ByVal value As Date)
    46. _datum = value
    47. raisepropertychanged()
    48. End Set
    49. End Property
    50. Private _groesse As Single
    51. Public Property Groesse() As Single
    52. Get
    53. Return _groesse
    54. End Get
    55. Set(ByVal value As Single)
    56. _groesse = value
    57. raisepropertychanged()
    58. End Set
    59. End Property
    60. Private _id As Integer
    61. Public Property ID() As Integer
    62. Get
    63. Return _id
    64. End Get
    65. Set(ByVal value As Integer)
    66. _id = value
    67. raisepropertychanged()
    68. End Set
    69. End Property
    70. Private _hintergrund_groesse As String
    71. Public Property Hintergrund_Groesse() As String
    72. Get
    73. Return _hintergrund_groesse
    74. End Get
    75. Set(ByVal value As String)
    76. _hintergrund_groesse = value
    77. raisepropertychanged()
    78. End Set
    79. End Property
    80. End Class



    Ich erkenne einfach nicht, was da falsch ist. :(

    Gruß

    eddi
    Hallo

    Ich probiers vom Handy.

    Setze mal einen haltepunkt in einem Setter eines Properties deiner Klasse. Du wirst sehen das sich da nix tut. Das liegt daran das du die in den CellTemplates nicht mit TwoWay bindest.

    Zumindest meine vermutung. Hab nur schnell drübergeguckt.

    Aber warum eigentlich für eine normale Textbox ein CellTemplate? Reicht doch eine TextColumn oder?

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Hallo Sascha,

    dass sich in den Propertys nichts tut hab ich gestern schon festgestellt. Die Bindung auf TwoWay umzustellen war auch mein erster Gedanke. Leider ohne Erfolg. Habe das Binding der Itemssource und die einzelnen Bindings der Spalten auf TwoWay umgestellt, aber ohne Erfolg.

    Mit der nromalen TextColumn kan ich bei den Einstellungen einfach nicht zurecht. Z.B. wusste ich nicht wie man an den Text rankommt und ihn formatiert. Auch mit dem Background der nomalen Spalte klappte es nicht.

    Vermutlich setzt ich jetzt erst mal ein neues Miniprojekt auf und vergleiche mein Vorgehen zum 3. Mal mit deinem Beispiel aus Teil 2.

    Gruß

    eddi
    Ein Miniprojekt ist immer eine gute Idee und ist ja in diesem Fall in ein paar Minuten aufgesetzt.

    Dann schau ich gerne drüber.

    Probier mal den Mode auf "TwoWay" und UpdateSourceTrigger auf "PropertyChanged". Setze einen Haltepunkt im Setter des Properties. Da muss er reinlaufen sonst stimmt was nicht.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Danke!
    Der UpdateSourceTrigger war das Problem. Bei automatisch generierten Spalten funktionierte in dem Miniprojekt alles. Nachdem ich sie dann manuell erstellt hab nicht mehr. Durch den UpdateSourceTrigger funktionierte es dann wieder.
    Verstehen kann ich es allerdings ehrlich gesagt nicht. Wenn der Cursor die Zeile verlässt, dann müsste doch die Nachricht, dass eine Änderung stattfand an das Property raus, oder?

    Gruß

    eddi

    eichseinet schrieb:

    Wenn der Cursor die Zeile verlässt, dann müsste doch die Nachricht, dass eine Änderung stattfand an das Property raus, oder?

    Eigentlich ja, aber ich kann mich erinnern das da einiges manchesmal ein merkwürdiges Verhalten an den Tag legt was CellTemplates betrifft.

    Freut mich das es nun klappt.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Mit einer DataGridTextColumn funktioniert es tatsächlich auch ohne die Angabe des UpdateSourceTrigger (gerade gestestet). Dafür gibt's da wieder ungelöste Probleme mit dem Zugriff auf den Text und den Background. Daher lasst ich es wie es ist. Zeilen spart es im XAML auch keine, soweit ich das gesehen habe.
    Den UpdateSourceTrigger auf PropertyChanged zu setzten löst mir sogar ein weiteres Problem in meinem richtigen Projekt.

    Danke nochmal. Gruß
    eddi