none
WPF - Sortierung nach Aktualisierung Datagrid RRS feed

  • Frage

  • Hallo,

    wenn ich ein Datagrid aktualisiere verliert er die vom User voreingestellte Sortierung. 

    Ich nutze die enthaltene Sortierungsmöglichkeit vom Datagrid.
    Die Daten werden mit CollectionViewSource.GetDefaultView an das ItemSource übergeben.

    Wie kann ich die Sortierung vorher auslesen und dann wieder nach der Aktualisierung setzen?

    Danke

    Ralf

    Dienstag, 14. November 2017 11:24

Antworten

  • Hi Ralf,
    hier mal ein Beispiel des ViewModels zum Laden der Daten mit dem EF aus einer Datenbank. Ich nutze Database First. Die mit dem Designer erzeugte Entity-Klasse heißt Window22Tab1. Die mit dem Designer erzeugte Context-Klasse heißt Windo22DemoDBEntities. Der Nachteil dieser Lösung ist das fehlende Tracking, um Änderungen rückzuspeichern. Wenn Du Änderungfen rückspeichern willst, dann baue besser eine Klasse mit DbSet-Eigenschaften und nutze diese als Repository.

    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Linq;
    using System.Runtime.CompilerServices;
    using System.Windows;
    using System.Windows.Data;
    using System.Windows.Input;
    
    namespace WpfApp1CS
    {
    
      public class Window22VM : INotifyPropertyChanged
      {
        /// <summary>
        /// Eigenschaft für Command-Bindung
        /// </summary>
        public ICommand Cmd { get { return new RelayCommand(CmdExec); } }
        /// <summary>
        /// Methode, die bei Command-Auslösung abzuarbeiten ist und neuen Client anzeigt
        /// </summary>
        /// <param name="obj">CommandParameter</param>
        private void CmdExec(object obj) { DatenNeuLaden(); }
    
        private CollectionViewSource cvs = new CollectionViewSource();
        private ObservableCollection<Tab1> col = new ObservableCollection<Tab1>();
        private SortDescriptionCollection sortcol;
    
        public ICollectionView Daten
        {
          get
          {
            if (cvs.View == null)
            {
              cvs.Source = col;
              if (sortcol != null)
                foreach (var sc in sortcol) cvs.View.SortDescriptions.Add(sc);
            }
            return cvs.View;
          }
        }
    
        private void DatenNeuLaden()
        {
          if (cvs.View != null) sortcol = cvs.SortDescriptions;
          col.Clear();
    
          Windo22DemoDBEntities ctx = new Windo22DemoDBEntities();
          foreach (var item in from t in ctx.Tab1 select t) col.Add(item);
    
          cvs.Source = null;
          OnPropertyChanged(nameof(Daten));
        }
    
        #region  OnPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged([CallerMemberName] string propName = "") =>
          PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
        #endregion
    
      }
    }


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    Dienstag, 14. November 2017 19:02

Alle Antworten

  • Hi Ralf,
    merke Dir vor der Neuzuweisung der Datenobjekte die Sortierung und weise sie dann erneut zu, z.B. so:

    XAML:

    <Window x:Class="WpfApp1CS.Window21"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfApp1CS"
            mc:Ignorable="d"
            Title="Window21" Height="300" Width="300">
      <Window.Resources>
        <local:Window21VM x:Key="vm"/>
        <Style TargetType="Button">
          <Setter Property="Margin" Value="5"/>
        </Style>
      </Window.Resources>
      <StackPanel DataContext="{StaticResource vm}">
        <Button Content="Neu Laden" Command="{Binding Cmd}" />
        <DataGrid Name="dg" ItemsSource="{Binding Daten}"/>
      </StackPanel>
    </Window>

    ViewModel:

    using System;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Runtime.CompilerServices;
    using System.Windows;
    using System.Windows.Data;
    using System.Windows.Input;
    
    namespace WpfApp1CS
    {
      public class Window21VM : INotifyPropertyChanged
      {
        /// <summary>
        /// Eigenschaft für Command-Bindung
        /// </summary>
        public ICommand Cmd { get { return new RelayCommand(CmdExec); } }
        /// <summary>
        /// Methode, die bei Command-Auslösung abzuarbeiten ist und neuen Client anzeigt
        /// </summary>
        /// <param name="obj">CommandParameter</param>
        private void CmdExec(object obj) { DatenNeuLaden(); }
    
        private CollectionViewSource cvs = new CollectionViewSource();
        private ObservableCollection<Window21Data> col = new ObservableCollection<Window21Data>();
        private Random rnd = new Random();
        private SortDescriptionCollection sortcol;
    
        public ICollectionView Daten
        {
          get
          {
            if (cvs.View == null)
            {
              cvs.Source = col;
              if (sortcol != null)
                foreach (var sc in sortcol) cvs.View.SortDescriptions.Add(sc);
            }
            return cvs.View;
          }
        }
    
        private void DatenNeuLaden()
        {
          if (cvs.View != null) sortcol = cvs.SortDescriptions;
          col.Clear();
          for (int i = 1; i < 100; i++)
            col.Add(new Window21Data() { ID = rnd.Next(1, 100), Info = $"Info {rnd.Next(1, 1000)}" });
          cvs.Source = null;
          OnPropertyChanged(nameof(Daten));
        }
    
        #region  OnPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged([CallerMemberName] string propName = "") =>
          PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
        #endregion
    
        public class Window21Data
        {
          public int ID { get; set; }
          public string Info { get; set; }
        }
      }
    }


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    Dienstag, 14. November 2017 13:01
  • Hallo,

    ich fülle die Daten mit Entity Framework.

    Durch if ((((ListCollectionView)dgDaten.ItemsSource).SortDescriptions).Count > 0) kann ich ja sehen das eine Sortierung da ist.

    Kann ich direkt darauf zugreifen und auslesen und dann wieder setzen?

    Danke

    Dienstag, 14. November 2017 15:50
  • Hi Ralf,
    wo die Daten herkommen ist egal. Die können auch über das EF geliefert werden. Ich habe Dir eine Lösung mit MVVM gezeigt, die funktioniert. Warum willst Du unbedingt etwas anderes machen? Welche Probleme hast Du mit meiner Lösung?

    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    Dienstag, 14. November 2017 16:10
  • Hi Peter,

    ich hab nur das Problem das ich nicht weis wie ich das EF in deine Lösung einbinde.

    Und da ich vergessen hatte das mit EF zu erwähnen hab ich das geantwortet, sollte keine Kritik an dir sein, eher unwissenheit bei mir.

    Dienstag, 14. November 2017 16:17
  • Hi Ralf,
    hier mal ein Beispiel des ViewModels zum Laden der Daten mit dem EF aus einer Datenbank. Ich nutze Database First. Die mit dem Designer erzeugte Entity-Klasse heißt Window22Tab1. Die mit dem Designer erzeugte Context-Klasse heißt Windo22DemoDBEntities. Der Nachteil dieser Lösung ist das fehlende Tracking, um Änderungen rückzuspeichern. Wenn Du Änderungfen rückspeichern willst, dann baue besser eine Klasse mit DbSet-Eigenschaften und nutze diese als Repository.

    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Linq;
    using System.Runtime.CompilerServices;
    using System.Windows;
    using System.Windows.Data;
    using System.Windows.Input;
    
    namespace WpfApp1CS
    {
    
      public class Window22VM : INotifyPropertyChanged
      {
        /// <summary>
        /// Eigenschaft für Command-Bindung
        /// </summary>
        public ICommand Cmd { get { return new RelayCommand(CmdExec); } }
        /// <summary>
        /// Methode, die bei Command-Auslösung abzuarbeiten ist und neuen Client anzeigt
        /// </summary>
        /// <param name="obj">CommandParameter</param>
        private void CmdExec(object obj) { DatenNeuLaden(); }
    
        private CollectionViewSource cvs = new CollectionViewSource();
        private ObservableCollection<Tab1> col = new ObservableCollection<Tab1>();
        private SortDescriptionCollection sortcol;
    
        public ICollectionView Daten
        {
          get
          {
            if (cvs.View == null)
            {
              cvs.Source = col;
              if (sortcol != null)
                foreach (var sc in sortcol) cvs.View.SortDescriptions.Add(sc);
            }
            return cvs.View;
          }
        }
    
        private void DatenNeuLaden()
        {
          if (cvs.View != null) sortcol = cvs.SortDescriptions;
          col.Clear();
    
          Windo22DemoDBEntities ctx = new Windo22DemoDBEntities();
          foreach (var item in from t in ctx.Tab1 select t) col.Add(item);
    
          cvs.Source = null;
          OnPropertyChanged(nameof(Daten));
        }
    
        #region  OnPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged([CallerMemberName] string propName = "") =>
          PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
        #endregion
    
      }
    }


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    Dienstag, 14. November 2017 19:02