none
DataGridRows mit gleichem Spalteneintrag markieren

    Frage

  • 0

    Versuche seit gerstern abend krampfhaft in eienm DataGrid alle Rows zu markieren, welche in der zweiten Spalte den identischen Text stehen haben.

    Genauso soll bei allen Rows wieder die Markierung entfernt werden, wenn die Row markiert ist und geklickt wird. Ich verwende dazu das SelectionChanges-Ereignis. Ich habe den Code beigefügt. Das PRoblem ist eben, das der Code korrekt abgearbeitet wird, aber immer nur die geklickte Zeile markiert wird, obwohl  mehrere Zeilen mit gleicher Auftragsnummer vorhanden sind. Woran kann das liegen?

    Hier der Code:

      private void dg_Visudaten_SelectionChanged(object sender, SelectionChangedEventArgs e)
            {
                //// Mehrere DataGridRows dürfen angewählt werden
                dg_Visudaten.SelectionMode = (DataGridSelectionMode) SelectionMode.Multiple;
                
                //// Variable für den Text in der Spalte 
                string auftragsNummer;
                
                
                //if(sender.GetType() != typeof(DataGrid))
                //    return;
    
    
                //// Ereignis abmelden
                dg_Visudaten.SelectionChanged -= dg_Visudaten_SelectionChanged;
    
    
                //// Wurde eine DataGridRow neu markiert (ausgewählt)?
                if(e.AddedItems.Count > 0)
                {
                    //// Auftragsnummer der neu markierten Zeile auslesen
                    auftragsNummer = ((DataRowView) (e.AddedItems[0])).Row["Auftragsnr"].ToString();
    
                    //// Alle Zeilen im DataGrid durchlaufen und auf identische "Auftragsnummer" prüfen. Ist die "Auftragsnummer" identisch, die DataGridRow.IsSelected markieren
                    for (int i = 0; i < dg_Visudaten.Items.Count; i++)
                    {
                        DataGridRow dgRow = (DataGridRow) dg_Visudaten.ItemContainerGenerator.ContainerFromIndex(i);
                        if (((DataRowView)(dg_Visudaten.Items[i])).Row["Auftragsnr"].ToString().Trim() == auftragsNummer)
                            dgRow.IsSelected = true;
                    }
                }
    
                //// Wurde eine DataGridRow die markiert war abgewählt ?
                if (e.RemovedItems.Count > 0)
                {
                    //// Auftragsnummer der abgewählten Zeile auslesen
                    auftragsNummer = ((DataRowView)(e.RemovedItems[0])).Row["Auftragsnr"].ToString();
    
                    //// Alle Zeilen im DataGrid durchlaufen und auf identische "Auftragsnummer" prüfen. Ist die "Auftragsnummer" identisch, die DataGridRow.IsSelected deselektieren
                    for (int i = 0; i < dg_Visudaten.Items.Count; i++)
                    {
                        DataGridRow dgRow = (DataGridRow)dg_Visudaten.ItemContainerGenerator.ContainerFromIndex(i);
                        if (((DataRowView)(dg_Visudaten.Items[i])).Row["Auftragsnr"].ToString().Trim() == auftragsNummer)
                            dgRow.IsSelected = false;
                    }
                }
    
                //// Ereignis wieder anmelden
                dg_Visudaten.SelectionChanged += dg_Visudaten_SelectionChanged;
    }


    oema von MSDN

    Mittwoch, 26. Dezember 2012 19:05

Antworten

  • Hallo,

    eine mögliche Lösung für eine gebundene DataView:

    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Linq;
    using System.Windows;
    using System.Windows.Controls;
    
    namespace ElmarBoye.Samples.Wpf
    {
        public partial class GridSelectionWindow : Window
        {
            public GridSelectionWindow()
            {
                InitializeComponent();
            }
    
            private void Window_Loaded(object sender, RoutedEventArgs e)
            {
                this.dataGrid1.ItemsSource = CreateSampleTable().DefaultView;
                this.dataGrid1.SelectionMode = DataGridSelectionMode.Extended;
                this.dataGrid1.SelectionChanged += dataGrid1_SelectionChanged;;
            }
    
            private DataTable CreateSampleTable()
            {
                var table = new DataTable("Tabelle");
                table.Columns.AddRange(new[]
                {
                    new DataColumn("Id", typeof(int)),
                    new DataColumn("Auftragsnr", typeof(string))
                });
                table.PrimaryKey = new [] { table.Columns["Id"] };
    
                for (int index = 0; index < 10000; index++)
                {
                    table.Rows.Add(index, (index % 10).ToString());
                }
                table.AcceptChanges();
                return table;
            }
    
    
            private void dataGrid1_SelectionChanged(object sender, SelectionChangedEventArgs e)
            {
                const string columnName = "Auftragsnr";
    
                DataGrid grid = sender as DataGrid;
                Console.WriteLine("SelectionChanged {0} / {1}",
                    grid.SelectedItems.Count, grid.SelectedCells.Count);
    
                grid.SelectionChanged -= dataGrid1_SelectionChanged;
                try
                {
    
                    var removedRows = new List<DataRowView>();
                    var addedRows = new List<DataRowView>();
    
                    if (e.RemovedItems != null && e.RemovedItems.Count > 0)
                    {
                        // abgewählte Werte (eindeutig)
                        string[] removedValues = e.RemovedItems.Cast<DataRowView>()
                            .Select(row => row[columnName] as string)
                            .Distinct().ToArray();
    
                        // Durchlaufen der ausgewählen Elemente (hier DataRowView)
                        foreach (DataRowView rowView in grid.SelectedItems.Cast<DataRowView>())
                        {
                            var compareValue = rowView[columnName] as string;
                            if (removedValues.Any(columnValue => String.Compare(
                                columnValue, compareValue, StringComparison.OrdinalIgnoreCase) == 0))
                            {
                                removedRows.Add(rowView);
                            }
                        }
                    }
    
                    if (e.AddedItems != null && e.AddedItems.Count > 0)
                    {
                        // neue Werte (eindeutig)
                        string[] addedValues = e.AddedItems.Cast<DataRowView>()
                            .Select((row) => row[columnName] as string)
                            .Distinct().ToArray();
    
                        // Durchlaufen der gebundenen DataView
                        var dataView = grid.ItemsSource as DataView;
                        foreach (DataRowView rowView in dataView)
                        {
                            var compareValue = rowView[columnName] as string;
                            if (addedValues.Any(columnValue => String.Compare(
                                    columnValue, compareValue, StringComparison.OrdinalIgnoreCase) == 0))
                            {
                                // ggf. Überschneidungen entfernen
                                removedRows.Remove(rowView); 
                                if (!grid.SelectedItems.Contains(rowView))
                                    addedRows.Add(rowView);
                            }
                        }
                    }
    
                    // alte abwählen bzw. neue auswählen
                    removedRows.ForEach(row => grid.SelectedItems.Remove(row));
                    addedRows.ForEach(row => grid.SelectedItems.Add(row));
                }
                finally
                {
                    grid.SelectionChanged += dataGrid1_SelectionChanged;
                }
            }
        }
    }
    

    Um Probleme durch die Virtualisierung zu umgehen, arbeitet die Auswahl über die SelectedItems und versucht nicht IsSelected zu verändern. Kleiner Nachteil bei größeren Treffer-Mengen: Es ist nicht gerade das schnellste - wobei ich fürs Beispiel etwas übertrieben haben dürfte ;)

    Gruß Elmar

    Donnerstag, 27. Dezember 2012 10:32

Alle Antworten

  • Hallo,

    eine mögliche Lösung für eine gebundene DataView:

    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Linq;
    using System.Windows;
    using System.Windows.Controls;
    
    namespace ElmarBoye.Samples.Wpf
    {
        public partial class GridSelectionWindow : Window
        {
            public GridSelectionWindow()
            {
                InitializeComponent();
            }
    
            private void Window_Loaded(object sender, RoutedEventArgs e)
            {
                this.dataGrid1.ItemsSource = CreateSampleTable().DefaultView;
                this.dataGrid1.SelectionMode = DataGridSelectionMode.Extended;
                this.dataGrid1.SelectionChanged += dataGrid1_SelectionChanged;;
            }
    
            private DataTable CreateSampleTable()
            {
                var table = new DataTable("Tabelle");
                table.Columns.AddRange(new[]
                {
                    new DataColumn("Id", typeof(int)),
                    new DataColumn("Auftragsnr", typeof(string))
                });
                table.PrimaryKey = new [] { table.Columns["Id"] };
    
                for (int index = 0; index < 10000; index++)
                {
                    table.Rows.Add(index, (index % 10).ToString());
                }
                table.AcceptChanges();
                return table;
            }
    
    
            private void dataGrid1_SelectionChanged(object sender, SelectionChangedEventArgs e)
            {
                const string columnName = "Auftragsnr";
    
                DataGrid grid = sender as DataGrid;
                Console.WriteLine("SelectionChanged {0} / {1}",
                    grid.SelectedItems.Count, grid.SelectedCells.Count);
    
                grid.SelectionChanged -= dataGrid1_SelectionChanged;
                try
                {
    
                    var removedRows = new List<DataRowView>();
                    var addedRows = new List<DataRowView>();
    
                    if (e.RemovedItems != null && e.RemovedItems.Count > 0)
                    {
                        // abgewählte Werte (eindeutig)
                        string[] removedValues = e.RemovedItems.Cast<DataRowView>()
                            .Select(row => row[columnName] as string)
                            .Distinct().ToArray();
    
                        // Durchlaufen der ausgewählen Elemente (hier DataRowView)
                        foreach (DataRowView rowView in grid.SelectedItems.Cast<DataRowView>())
                        {
                            var compareValue = rowView[columnName] as string;
                            if (removedValues.Any(columnValue => String.Compare(
                                columnValue, compareValue, StringComparison.OrdinalIgnoreCase) == 0))
                            {
                                removedRows.Add(rowView);
                            }
                        }
                    }
    
                    if (e.AddedItems != null && e.AddedItems.Count > 0)
                    {
                        // neue Werte (eindeutig)
                        string[] addedValues = e.AddedItems.Cast<DataRowView>()
                            .Select((row) => row[columnName] as string)
                            .Distinct().ToArray();
    
                        // Durchlaufen der gebundenen DataView
                        var dataView = grid.ItemsSource as DataView;
                        foreach (DataRowView rowView in dataView)
                        {
                            var compareValue = rowView[columnName] as string;
                            if (addedValues.Any(columnValue => String.Compare(
                                    columnValue, compareValue, StringComparison.OrdinalIgnoreCase) == 0))
                            {
                                // ggf. Überschneidungen entfernen
                                removedRows.Remove(rowView); 
                                if (!grid.SelectedItems.Contains(rowView))
                                    addedRows.Add(rowView);
                            }
                        }
                    }
    
                    // alte abwählen bzw. neue auswählen
                    removedRows.ForEach(row => grid.SelectedItems.Remove(row));
                    addedRows.ForEach(row => grid.SelectedItems.Add(row));
                }
                finally
                {
                    grid.SelectionChanged += dataGrid1_SelectionChanged;
                }
            }
        }
    }
    

    Um Probleme durch die Virtualisierung zu umgehen, arbeitet die Auswahl über die SelectedItems und versucht nicht IsSelected zu verändern. Kleiner Nachteil bei größeren Treffer-Mengen: Es ist nicht gerade das schnellste - wobei ich fürs Beispiel etwas übertrieben haben dürfte ;)

    Gruß Elmar

    Donnerstag, 27. Dezember 2012 10:32
  • Hallo, danke für die Info, das hat mit weitergeholfen.

    oema von MSDN

    Sonntag, 30. Dezember 2012 00:17