Datagrid mit Auswahl von keiner/allen Zeilen - Zellenzugriff

  • WPF

Es gibt 4 Antworten in diesem Thema. Der letzte Beitrag () ist von jan99.

    Datagrid mit Auswahl von keiner/allen Zeilen - Zellenzugriff

    Moin!

    ich möchte in einem WPF-Datagrid Daten (ohne DB-Anbindung) darstellen. Die Formdefinition sieht wie folgt aus:

    XML-Quellcode

    1. <Window x:Name="DLG_GSEW_ImportHistorie" x:Class="DLG_GSEW_ImportHistorie"
    2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    4. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    5. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    6. mc:Ignorable="d" Title="GSEW Historie importieren" ResizeMode="NoResize" Height="468.651" Width="1000.969" WindowStartupLocation="CenterScreen">
    7. <Grid Margin="0,0,-17,0" HorizontalAlignment="Left">
    8. <Label x:Name="lb_Info" Content="wählen Sie, die Einträge übertragen werden sollen." HorizontalAlignment="Left" Height="30" Margin="10,10,0,0" VerticalAlignment="Top" Width="303" RenderTransformOrigin="0.526,1.1"/>
    9. <Button x:Name="bt_Cancel" Content="Abbruch" HorizontalAlignment="Left" Height="30" Margin="19,391,0,0" VerticalAlignment="Top" Width="96" ToolTip="Beendet diese Funktion" IsCancel="True" IsDefault="True"/>
    10. <Button x:Name="bt_Help" Content="Hilfe" HorizontalAlignment="Left" Height="30" Margin="308,391,0,0" VerticalAlignment="Top" Width="88" ToolTip="Hilfestellung"/>
    11. <Button x:Name="bt_Action" Content="Abschicken" Height="30" Width="88" Margin="172,391,267,0" VerticalAlignment="Top" ToolTip="sichern des LayerStatus"/>
    12. <DataGrid Name="dgHistorie" Margin="10,45,-455,70"></DataGrid>
    13. <Button x:Name="bt_FilterAll" Content="ALLE" HorizontalAlignment="Left" Height="28" Margin="777,393,-338,0" VerticalAlignment="Top" Width="88" ToolTip="Filter anwenden"/>
    14. <Button x:Name="bt_FilterNo" Content="KEINE" Width="88" Height="28" Margin="879,393,-440,0" VerticalAlignment="Top" RenderTransformOrigin="1.135,0.429" ToolTip="Filter löschen"/>
    15. </Grid>
    16. </Window>


    Den nachfolgenden Code für die Datenbefüllung habe ich im Weg gefunden. In der ersten Spalte soll eine Checkbox sein, damit die Zeilen für nachfolgende Schritte ausgewählt werden können. Deshalb habe ich auch bei der Bestückung den Wert Import hinzugeführt.

    VB.NET-Quellcode

    1. Imports System.Text.RegularExpressions
    2. Imports System.Collections.Generic
    3. Imports System.Windows
    4. Public Class DLG_GSEW_ImportHistorie
    5. Public _MyApplication As Mum.Geo.Client.Application
    6. Public Sub New(MyApplication As Mum.Geo.Client.Application)
    7. ' Dieser Aufruf ist für den Designer erforderlich.
    8. InitializeComponent()
    9. _MyApplication = MyApplicationa
    10. Dim Historie As List(Of User) = New List(Of User)()
    11. Historie.Add(New User() With {
    12. .Import = False,
    13. .Id = 1,
    14. .Name = "John Doe",
    15. .Birthday = New DateTime(1971, 7, 23)
    16. })
    17. Historie.Add(New User() With {
    18. .Import = False,
    19. .Id = 2,
    20. .Name = "Jane Doe",
    21. .Birthday = New DateTime(1974, 1, 17)
    22. })
    23. Historie.Add(New User() With {
    24. .Import = False,
    25. .Id = 3,
    26. .Name = "Sammy Doe",
    27. .Birthday = New DateTime(1991, 9, 2)
    28. })
    29. dgHistorie.ItemsSource = Historie
    30. End Sub
    31. ''' <summary>
    32. ''' die gesamte Auswahl aufheben
    33. ''' </summary>
    34. Private Sub bt_FilterNo_Click(sender As Object, e As RoutedEventArgs) Handles bt_FilterNo.Click
    35. SetSelection(False)
    36. End Sub
    37. ''' <summary>
    38. ''' die gesamte Auswahl setzen
    39. ''' </summary>
    40. Private Sub bt_FilterAll_Click(sender As Object, e As Windows.RoutedEventArgs) Handles bt_FilterAll.Click
    41. SetSelection(True)
    42. End Sub
    43. Private Sub SetSelection(Status As Boolean)
    44. For i As Integer = 0 To dgHistorie.Items.Count - 1
    45. Next
    46. End Sub
    47. Public Class User
    48. Public Property Import As Boolean
    49. Public Property Id As Integer
    50. Public Property Name As String
    51. Public Property Birthday As DateTime
    52. End Class
    53. End Class


    Nun habe ich zwei Fragen:

    1.) Wie kann ich auf die Checkboxen zugreifen um die Auswahl für alle zu de/aktivieren? (Funktion: SetSelection)

    2.) Dann suche ich einen Weg einmal durch alle Zeilen zu laufen und dabei die Spalte 1 für die Zeilen auszulesen, deren Checkbox true ist.

    Irgendwie komme ich mit den gefundenen Beispielen im Web nicht klar.

    Gruß Jan
    Hallo Jan

    Erstmal würde ich dir raten mit Binding zu arbeiten. Das macht unter WPF so einiges viel einfacher.
    Wenn du wissen willst wer der User Import auf 'True' hat dann fragst du die Daten ab. Nicht das DataGrid.

    Hier der Code meines Tests:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Class MainWindow
    2. Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
    3. Dim Historie As List(Of User) = New List(Of User)()
    4. Historie.Add(New User() With {
    5. .Import = False,
    6. .Id = 1,
    7. .Name = "John Doe",
    8. .Birthday = New DateTime(1971, 7, 23)
    9. })
    10. Historie.Add(New User() With {
    11. .Import = False,
    12. .Id = 2,
    13. .Name = "Jane Doe",
    14. .Birthday = New DateTime(1974, 1, 17)
    15. })
    16. Historie.Add(New User() With {
    17. .Import = False,
    18. .Id = 3,
    19. .Name = "Sammy Doe",
    20. .Birthday = New DateTime(1991, 9, 2)
    21. })
    22. Persons = New ObservableCollection(Of User)(Historie)
    23. DataContext = Me
    24. End Sub
    25. Private _persons As ObservableCollection(Of User)
    26. Public Property Persons() As ObservableCollection(Of User)
    27. Get
    28. Return _persons
    29. End Get
    30. Set(ByVal value As ObservableCollection(Of User))
    31. _persons = value
    32. End Set
    33. End Property
    34. Private _showImportedUserCommand As ICommand
    35. Public Property ShowImportedUserCommand() As ICommand
    36. Get
    37. If _showImportedUserCommand Is Nothing Then _showImportedUserCommand = New RelayCommand(AddressOf ShowImportedUserCommand_Execute)
    38. Return _showImportedUserCommand
    39. End Get
    40. Set(ByVal value As ICommand)
    41. _showImportedUserCommand = value
    42. End Set
    43. End Property
    44. Private Sub ShowImportedUserCommand_Execute(obj As Object)
    45. MessageBox.Show(String.Join(Environment.NewLine, Persons.Where(Function(x) x.Import).ToList.Select(Function(u) u.Name)))
    46. End Sub
    47. End Class
    48. Public Class User
    49. Public Property Import As Boolean
    50. Public Property Id As Integer
    51. Public Property Name As String
    52. Public Property Birthday As DateTime
    53. End Class


    Und der XAML dazu.

    XML-Quellcode

    1. <Grid>
    2. <Grid.RowDefinitions>
    3. <RowDefinition Height="*"/>
    4. <RowDefinition Height="Auto"/>
    5. </Grid.RowDefinitions>
    6. <DataGrid AutoGenerateColumns="True" ItemsSource="{Binding Persons}">
    7. </DataGrid>
    8. <StackPanel Orientation="Horizontal" Grid.Row="1">
    9. <Button Content="Alle mit 'Import = True'" Command="{Binding ShowImportedUserCommand}"/>
    10. </StackPanel>
    11. </Grid>


    PS: Für die Commands verwende ich meine RelayCommand-Klasse:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. '-----------------------------------------------------------------------
    2. ' <copyright file="C:\VB-Paradise_Projects\WpfNotes2\WpfNotes2_Project\WpfNotes.ViewModel\RelayCommand.vb" company="SPS Software Solution">
    3. ' Author: Sascha Patschka
    4. ' Copyright (c) SPS Software Solution. All rights reserved.
    5. ' </copyright>
    6. '-----------------------------------------------------------------------
    7. Imports System.Windows.Input
    8. ''' <summary>
    9. ''' Diese Klasse Implementiert das ICommand Interface, so muss man nicht in jeder Klasse eines ViewModel alles selbst implementieren.
    10. ''' Einfach eine Command wie folgt Instanzieren:
    11. ''' MyCommand = New RelayCommand(AddressOf MyCommand_Execute, AddressOf MyCommand_CanExecute)
    12. ''' </summary>
    13. Public Class RelayCommand : Implements ICommand
    14. #Region " Fields "
    15. ReadOnly _execute As Action(Of Object)
    16. ReadOnly _canExecute As Predicate(Of Object)
    17. #End Region
    18. #Region " Constructors"
    19. ''' <summary>
    20. ''' Erstellt einen neuen Command welcher NUR Executed werden kann.
    21. ''' </summary>
    22. ''' <param name="execute">The execution logic.</param>
    23. ''' <remarks></remarks>
    24. Public Sub New(execute As Action(Of Object))
    25. Me.New(execute, Nothing)
    26. End Sub
    27. ''' <summary>
    28. ''' Erstellt einen neuen Command welcher sowohl die Execute als auch die CanExecute Logik beinhaltet.
    29. ''' </summary>
    30. ''' <param name="execute">Die Logik für Execute.</param>
    31. ''' <param name="canExecute">Die Logik für CanExecute.</param>
    32. ''' <remarks></remarks>
    33. Public Sub New(execute As Action(Of Object), canExecute As Predicate(Of Object))
    34. If execute Is Nothing Then
    35. Throw New ArgumentNullException("execute")
    36. End If
    37. _execute = execute
    38. _canExecute = canExecute
    39. End Sub
    40. #End Region
    41. #Region " ICommand Members "
    42. ''' <summary>
    43. ''' Setzt die CanExecute-Methode des ICommand-Interfaces auf True oder False
    44. ''' </summary>
    45. ''' <param name="parameter"></param>
    46. ''' <returns>Gibt zurück ob die Aktion ausgeführt werden kann oder nicht</returns>
    47. ''' <remarks>
    48. ''' Benutzt DebuggerStepThrough from System.Diagnostics
    49. ''' Der Debugger überspringt diese Prozedur also, es sei den es wird explizit ein Haltepunkt gesetzt.
    50. ''' </remarks>
    51. <DebuggerStepThrough>
    52. Public Function CanExecute(parameter As Object) As Boolean Implements ICommand.CanExecute
    53. Return _canExecute Is Nothing OrElse _canExecute(parameter)
    54. End Function
    55. ''' <summary>
    56. ''' Event welches geworfen wird wenn die Propertie CanExecuteChanged sich ändert.
    57. ''' </summary>
    58. ''' <remarks></remarks>
    59. Public Custom Event CanExecuteChanged As EventHandler Implements ICommand.CanExecuteChanged
    60. AddHandler(value As EventHandler)
    61. If _canExecute IsNot Nothing Then
    62. AddHandler CommandManager.RequerySuggested, value
    63. End If
    64. End AddHandler
    65. RemoveHandler(value As EventHandler)
    66. If _canExecute IsNot Nothing Then
    67. RemoveHandler CommandManager.RequerySuggested, value
    68. End If
    69. End RemoveHandler
    70. RaiseEvent(sender As Object, e As EventArgs)
    71. End RaiseEvent
    72. End Event
    73. ''' <summary>
    74. ''' Führt die Prozedur Execute des ICommand.Execute aus
    75. ''' </summary>
    76. ''' <param name="parameter"></param>
    77. ''' <remarks></remarks>
    78. Public Sub Execute(parameter As Object) Implements ICommand.Execute
    79. _execute(parameter)
    80. End Sub
    81. #End Region
    82. End Class



    Grüße
    Sascha
    Bilder
    • Import.PNG

      18,38 kB, 785×446, 60 mal angesehen
    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. ##

    Hi!
    erst einmal vielen Dank - versuche gerade den Code zu übernehmen. Für RelayCommand habe ich eine neue Klasse angelegt.

    Dann habe ich in der anderen Klasse die Codepassagen übernommen.

    Was jetzt noch angemerkt wird, dass es nicht definiert ist sind folgende Typen ICommand und ObservableCollection.



    Muss ich noch verweise setzen? Aber ICommand kann es wohl nicht sein, da dieses, so verstehe ich Deine Doku, bindet diese ein.

    ???

    Gruß Jan
    Hallo Jan

    Und wenn du nun in einen "Unterwellten" Text reinklickst und STRG+. drückst - was schlägt dir Visual Studio vor?
    Vermutlich das du Imports System.Collections.ObjectModel importieren solltest. Das machst du und schon klappt es. Oder du schreibst überall den vollqualifizierten Namen.

    PS: ICommand sollte aber ohne Import gehen in einem WPF Projekt?

    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. ##

    Moin!

    danke erst einmal. Imports wie angegeben ergänzt -> erfolgreich.

    In der Code-Klasse zur WPF (so bezeichne ich das einmal) musste auch noch ein

    VB.NET-Quellcode

    1. Imports System.Windows.Input


    werden.

    Werde jetzt aber erst wohl Donnerstag oder nach Ostern weitermachen können. Andere Server wollen mich haben! <X

    Jan