none
MVVM - DataGrid - ScrollIntoView?

    Frage

  • Hallo, wie in der letzten Frage beschrieben, ist mein Ausganszustand ein DataGrid:

                            <DataGrid Grid.Row="0" ItemsSource="{Binding Pruefling.Messpunkte}" AutoGenerateColumns="False" IsReadOnly="True" Width="1200" HorizontalAlignment="Left" Grid.ColumnSpan="2" MaxHeight="300">
                                <DataGrid.ColumnHeaderStyle>
                                    <Style TargetType="{x:Type DataGridColumnHeader}">
                                        <Setter Property="FontWeight" Value="Bold"/>
                                        <Setter Property="HorizontalAlignment" Value="Center"/>
                                        <Setter Property="HorizontalContentAlignment" Value="Center"/>
                                        <Setter Property="FontSize" Value="20"/>
                                    </Style>
                                </DataGrid.ColumnHeaderStyle>
                                <DataGrid.RowStyle>
                                    <Style TargetType="{x:Type DataGridRow}">
                                        <Setter Property="FontWeight" Value="Bold"/>
                                        <Setter Property="FontSize" Value="20"/>
                                    </Style>
                                </DataGrid.RowStyle>
                                <DataGrid.Columns>
                                    <DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
                                    <DataGridTextColumn Header="XMess" Binding="{Binding X_Mess_Kompensiert}">
                                        <DataGridTextColumn.ElementStyle>
                                            <Style TargetType="TextBlock">
                                                <Setter Property="Background">
                                                    <Setter.Value>
                                                        <MultiBinding Converter="{StaticResource conv}">
                                                            <Binding Path="X_Mess_Kompensiert"/>
                                                            <Binding Path="X_Soll"/>
                                                            <Binding Path="XMinTol"/>
                                                            <Binding Path="XMaxTol"/>
                                                        </MultiBinding>
                                                    </Setter.Value>
                                                </Setter>
                                            </Style>
                                        </DataGridTextColumn.ElementStyle>
                                    </DataGridTextColumn>
    ...

    Im ViewModel wird über AddMesswert() die Messpunkte-Zeilen innerhalb eines Prüflings gefüllt, sowie neue Inforamtionen ans View gesendet.

    private void AddMesswert()
    {      
    
                          // jeden 2. Messpunkt gasket berechnen
                                if (zaehlerMP % 2 == 1) Pruefling.Messpunkte[zaehlerMP].gasket_Mess = gasketBerechnen(zaehlerMP);
                                // jeden 4. Messpunkt Gasket (W1 und H1) berechnen
                                if (zaehlerMP % 4 == 3) Pruefling.Messpunkte[zaehlerMP].Gasket_Mess = GasketBerechnen(zaehlerMP).ToString();
                                // Messzeitpuntk eintragen
                                Pruefling.Messpunkte[zaehlerMP].Messzeitpunkt = DateTime.Now.ToString("dd.MM.yyyy HH:mm",CultureInfo.InvariantCulture);
                                // neuer Messpunkt
                                zaehlerMP++;
    ...
    }
    

    Wenn nun sehr viele Messpunkte vorhanden sind, sehe ich im View nur die ersten paar Zeilen der Messpunkte. Wie schafft man es nun, dass im View, die neu angelegte Zeile in den Focus gelangt? Aktuell muss ich im View über die rechte Scroll-Leiste den Pfeil nach unten anklicken, damit ich die gerade aktive Messpunktzeile sehen kann.

    Ich hoffe, das war verständlich formuliert.

    Vielen Dank an Euch.

    Viele Grüße
    Martin


    Freitag, 30. November 2018 09:29

Antworten

  • Hi Martin,
    mit Stefans Hinweis habe ich mal das alte Beispiel ergänzt.

    XAML

    <Window x:Class="WpfApp1.Window79"
            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:WpfApp1"
            xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
            mc:Ignorable="d"
            Title="Window79" Height="300" Width="400">
      <Window.Resources>
        <local:Window79VM x:Key="vm"/>
      </Window.Resources>
      <Grid DataContext="{StaticResource vm}">
        <Grid.ColumnDefinitions>
          <ColumnDefinition/>
          <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid Grid.Column="0">
          <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition Height="Auto"/>
          </Grid.RowDefinitions>
          <DataGrid Grid.Row="0" ItemsSource="{Binding ViewP}" AutoGenerateColumns="False" IsReadOnly="True">
            <DataGrid.Columns>
              <DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
            </DataGrid.Columns>
          </DataGrid>
          <Button Grid.Row="1" Content="neuer Prüfling" Command="{Binding Cmd}" CommandParameter="Pr" Margin="5"/>
        </Grid>
        <Grid Grid.Column="1" >
          <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition Height="Auto"/>
          </Grid.RowDefinitions>
          <DataGrid ItemsSource="{Binding Pruefling.Messpunkte}">
            <i:Interaction.Behaviors>
              <local:Window79Behavior/>
            </i:Interaction.Behaviors>
          </DataGrid>
          <Button Grid.Row="1" Content="neuer Messwert" Command="{Binding Cmd}" CommandParameter="Mw" Margin="5"/>
        </Grid>
      </Grid>
    </Window>

    Und dazu die Klassen:

    using System;
    using System.Collections.ObjectModel;
    using System.Collections.Specialized;
    using System.ComponentModel;
    using System.Runtime.CompilerServices;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Input;
    using System.Windows.Interactivity;
    
    namespace WpfApp1
    {
      public partial class Window79VM : INotifyPropertyChanged
      {
        /// <summary>
        /// Constructor
        /// </summary>
        public Window79VM()
        {
          cvsP.Source = dl.GetData();
          cvsP.View.CurrentChanged += (object sender, EventArgs e) =>
            {
              Pruefling = cvsP.View.CurrentItem as Window79DataP;
              OnPropertyChanged("Pruefling");
            };
        }
    
        /// <summary>
        /// DataLayer Instance
        /// </summary>
        Window79DL dl = new Window79DL();
    
        private CollectionViewSource cvsP = new CollectionViewSource();
        public ICollectionView ViewP { get { return cvsP.View; } }
    
        public Window79DataP Pruefling { get; set; }
    
        public ICommand Cmd { get { return new RelayCommand(CmdExec); } }
    
        private void CmdExec(object obj)
        {
          switch (obj.ToString())
          {
            case "Pr":
              dl.AddNewPruefling();
              cvsP.View.MoveCurrentToLast();
              break;
            case "Mw":
              dl.AddNewMesswert(Pruefling);
              break;
            default:
              break;
          }
        }
    
        #region  OnPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged([CallerMemberName] string propName = "") =>
          PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
        #endregion
      }
      /// <summary>
      /// Datenklasse des DataLayer zur Bereitstellung der Daten
      /// </summary>
      internal partial class Window79DL
      {
        ObservableCollection<Window79DataP> colP = new ObservableCollection<Window79DataP>();
    
        /// <summary>
        /// Liste der Prüflinge mit den Messdaten laden
        /// </summary>
        /// <returns></returns>
        internal ObservableCollection<Window79DataP> GetData()
        {
          for (int i = 1; i < 10; i++)
          {
            Window79DataP d = new Window79DataP() { ID = i, Name = $"Prüfling {i}" };
            colP.Add(d);
            for (int k = 1; k < 5; k++)
              d.Messpunkte.Add(new Window79DataM() { Messpunkt = $"M{i}{k}", Messwert = 1.1m * k * i, Abweichung = .1m * k * i });
          }
          return colP;
        }
        internal void AddNewPruefling() => colP.Add(new Window79DataP() { ID = 99, Name = "<neu>" });
        private int nr = 55; // Laufvariable für Simulation neuer Werte
        internal void AddNewMesswert(Window79DataP pr) => pr.Messpunkte.Add(new Window79DataM() { Messpunkt = $"M neu {nr++}", Messwert = 1.1m * nr, Abweichung = .1m * nr });
      }
      // Datenklasse für Prüfling
      public class Window79DataP
      {
        public int ID { get; set; }
        public string Name { get; set; }
        public ObservableCollection<Window79DataM> Messpunkte { get; set; } = new ObservableCollection<Window79DataM>();
      }
      // Datenklasse für Messpunkt
      public class Window79DataM : INotifyPropertyChanged
      {
        public string Messpunkt { get; set; }
        private decimal _messwert;
        public decimal Messwert
        {
          get { return this._messwert; }
          set { this._messwert = value; OnPropertyChanged(); }
        }
        public decimal Abweichung { get; set; }
    
        #region  OnPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged([CallerMemberName] string propName = "") =>
          PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
        #endregion
      }
      public class Window79Behavior : Behavior<DataGrid>
      {
        protected override void OnAttached() =>
          ((INotifyCollectionChanged)AssociatedObject.Items).CollectionChanged += Window79Behavior_CollectionChanged;
        protected override void OnDetaching() =>
          ((INotifyCollectionChanged)AssociatedObject.Items).CollectionChanged += Window79Behavior_CollectionChanged;
    
        private void Window79Behavior_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
          if (e.Action == NotifyCollectionChangedAction.Add)
          {
            // scroll the new item into view   
            AssociatedObject.ScrollIntoView(e.NewItems[0]);
          }
        }
    
      }
    }


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

    • Als Antwort vorgeschlagen Peter Fleischer Montag, 3. Dezember 2018 08:47
    • Als Antwort markiert mApO18 Montag, 3. Dezember 2018 09:51
    Freitag, 30. November 2018 10:49

Alle Antworten

  • Hi,

    schau mal HIER, das sollte auch mit einem DataGrid funktionieren.

    Gruß


    Freiberufler im Bereich Softwareentwicklung Von der PLC und Robotik zu VB.NET & C#, vorrangig WPF und UWP

    Freitag, 30. November 2018 10:01
  • Hi Martin,
    mit Stefans Hinweis habe ich mal das alte Beispiel ergänzt.

    XAML

    <Window x:Class="WpfApp1.Window79"
            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:WpfApp1"
            xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
            mc:Ignorable="d"
            Title="Window79" Height="300" Width="400">
      <Window.Resources>
        <local:Window79VM x:Key="vm"/>
      </Window.Resources>
      <Grid DataContext="{StaticResource vm}">
        <Grid.ColumnDefinitions>
          <ColumnDefinition/>
          <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid Grid.Column="0">
          <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition Height="Auto"/>
          </Grid.RowDefinitions>
          <DataGrid Grid.Row="0" ItemsSource="{Binding ViewP}" AutoGenerateColumns="False" IsReadOnly="True">
            <DataGrid.Columns>
              <DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
            </DataGrid.Columns>
          </DataGrid>
          <Button Grid.Row="1" Content="neuer Prüfling" Command="{Binding Cmd}" CommandParameter="Pr" Margin="5"/>
        </Grid>
        <Grid Grid.Column="1" >
          <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition Height="Auto"/>
          </Grid.RowDefinitions>
          <DataGrid ItemsSource="{Binding Pruefling.Messpunkte}">
            <i:Interaction.Behaviors>
              <local:Window79Behavior/>
            </i:Interaction.Behaviors>
          </DataGrid>
          <Button Grid.Row="1" Content="neuer Messwert" Command="{Binding Cmd}" CommandParameter="Mw" Margin="5"/>
        </Grid>
      </Grid>
    </Window>

    Und dazu die Klassen:

    using System;
    using System.Collections.ObjectModel;
    using System.Collections.Specialized;
    using System.ComponentModel;
    using System.Runtime.CompilerServices;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Input;
    using System.Windows.Interactivity;
    
    namespace WpfApp1
    {
      public partial class Window79VM : INotifyPropertyChanged
      {
        /// <summary>
        /// Constructor
        /// </summary>
        public Window79VM()
        {
          cvsP.Source = dl.GetData();
          cvsP.View.CurrentChanged += (object sender, EventArgs e) =>
            {
              Pruefling = cvsP.View.CurrentItem as Window79DataP;
              OnPropertyChanged("Pruefling");
            };
        }
    
        /// <summary>
        /// DataLayer Instance
        /// </summary>
        Window79DL dl = new Window79DL();
    
        private CollectionViewSource cvsP = new CollectionViewSource();
        public ICollectionView ViewP { get { return cvsP.View; } }
    
        public Window79DataP Pruefling { get; set; }
    
        public ICommand Cmd { get { return new RelayCommand(CmdExec); } }
    
        private void CmdExec(object obj)
        {
          switch (obj.ToString())
          {
            case "Pr":
              dl.AddNewPruefling();
              cvsP.View.MoveCurrentToLast();
              break;
            case "Mw":
              dl.AddNewMesswert(Pruefling);
              break;
            default:
              break;
          }
        }
    
        #region  OnPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged([CallerMemberName] string propName = "") =>
          PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
        #endregion
      }
      /// <summary>
      /// Datenklasse des DataLayer zur Bereitstellung der Daten
      /// </summary>
      internal partial class Window79DL
      {
        ObservableCollection<Window79DataP> colP = new ObservableCollection<Window79DataP>();
    
        /// <summary>
        /// Liste der Prüflinge mit den Messdaten laden
        /// </summary>
        /// <returns></returns>
        internal ObservableCollection<Window79DataP> GetData()
        {
          for (int i = 1; i < 10; i++)
          {
            Window79DataP d = new Window79DataP() { ID = i, Name = $"Prüfling {i}" };
            colP.Add(d);
            for (int k = 1; k < 5; k++)
              d.Messpunkte.Add(new Window79DataM() { Messpunkt = $"M{i}{k}", Messwert = 1.1m * k * i, Abweichung = .1m * k * i });
          }
          return colP;
        }
        internal void AddNewPruefling() => colP.Add(new Window79DataP() { ID = 99, Name = "<neu>" });
        private int nr = 55; // Laufvariable für Simulation neuer Werte
        internal void AddNewMesswert(Window79DataP pr) => pr.Messpunkte.Add(new Window79DataM() { Messpunkt = $"M neu {nr++}", Messwert = 1.1m * nr, Abweichung = .1m * nr });
      }
      // Datenklasse für Prüfling
      public class Window79DataP
      {
        public int ID { get; set; }
        public string Name { get; set; }
        public ObservableCollection<Window79DataM> Messpunkte { get; set; } = new ObservableCollection<Window79DataM>();
      }
      // Datenklasse für Messpunkt
      public class Window79DataM : INotifyPropertyChanged
      {
        public string Messpunkt { get; set; }
        private decimal _messwert;
        public decimal Messwert
        {
          get { return this._messwert; }
          set { this._messwert = value; OnPropertyChanged(); }
        }
        public decimal Abweichung { get; set; }
    
        #region  OnPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged([CallerMemberName] string propName = "") =>
          PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
        #endregion
      }
      public class Window79Behavior : Behavior<DataGrid>
      {
        protected override void OnAttached() =>
          ((INotifyCollectionChanged)AssociatedObject.Items).CollectionChanged += Window79Behavior_CollectionChanged;
        protected override void OnDetaching() =>
          ((INotifyCollectionChanged)AssociatedObject.Items).CollectionChanged += Window79Behavior_CollectionChanged;
    
        private void Window79Behavior_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
          if (e.Action == NotifyCollectionChangedAction.Add)
          {
            // scroll the new item into view   
            AssociatedObject.ScrollIntoView(e.NewItems[0]);
          }
        }
    
      }
    }


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

    • Als Antwort vorgeschlagen Peter Fleischer Montag, 3. Dezember 2018 08:47
    • Als Antwort markiert mApO18 Montag, 3. Dezember 2018 09:51
    Freitag, 30. November 2018 10:49
  • Hi Peter, danke für deine Demo. Welches Packet ist für die Behavior zu verwenden? Leider kann ich auf

    using System.Windows.Interactivity;

    nicht zugreifen.

    Freitag, 30. November 2018 15:53
  • Hi Martin,
    das musst über nuget laden (System.Windows.Interactivity.WPF):


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

    Freitag, 30. November 2018 16:00
  • Guten morgen Peter,

    danke für die Informationen. Die Routine

    Window79Behavior_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)

    wird momentan nur beim instanzieren des DataGrids aufgerufen. Es soll jedoch aktualsiert werden, sobald eine neue Messpunktzeile gefüllt wurde. Kann man die Window79Behavior_CollectionChanged() im ViewModel aufrufen? Über Pruefling.Messpunkte[zaehlerMP].(Eigenschaft) werden die Parameter in die Messpunktzeile geschrieben. Nach jeder neuen Zeile wird zaehlerMP eins hochgezählt.

    Ich hoffe, es war verständlich.
    Vielen Dank!

    Montag, 3. Dezember 2018 07:35
  • Hi Martin,
    genau das macht mein Beispiel. Vermutlich hast Du das Beispiel nicht codegenau für Tests übernommen. Wenn es nicht funktioniert, dann müsste man wissen, was Du an meinem Beispiel geändert hast.

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

    Montag, 3. Dezember 2018 08:42
  • Hi Martin,
    das Beispiel für ein DataGrid hatte ich Dir am Freitag, 30. November 2018 10:49 bereits gepostet:

    using System.Windows.Interactivity;

    public class Window79Behavior : Behavior<DataGrid> { protected override void OnAttached() => ((INotifyCollectionChanged)AssociatedObject.Items).CollectionChanged += Window79Behavior_CollectionChanged; protected override void OnDetaching() => ((INotifyCollectionChanged)AssociatedObject.Items).CollectionChanged += Window79Behavior_CollectionChanged; private void Window79Behavior_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { if (e.Action == NotifyCollectionChangedAction.Add) { // scroll the new item into view AssociatedObject.ScrollIntoView(e.NewItems[0]); } } }

    Und im XAML ist dazu einzufügen:

    <Window x:Class="WpfApp1.Window79"
    ...
            xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
            mc:Ignorable="d"
            Title="Window79" Height="300" Width="400">
    ...
          <DataGrid ItemsSource="{Binding Pruefling.Messpunkte}">
            <i:Interaction.Behaviors>
              <local:Window79Behavior/>
            </i:Interaction.Behaviors>
          </DataGrid>


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


    Montag, 3. Dezember 2018 08:45
  • Hi Peter, ich versuch es zu verstehen. Kann es sein, dass Window79Behavior_CollectionChanged() nur aufgerufen wird, wenn eine neuer Messpunkt über

    pr.Messpunkte.Add(...)

    hinzugefügt wird? Falls, ja, hilft mir das nicht weiter, da meine Messpunktzeilen schon vorher existieren. Die Messwerte werden nachträglich Zeile für Zeile hinzufügt. Und zwar über Pruefling.Messpunkt.XMess = 3 . zum Beispiel.

    Montag, 3. Dezember 2018 09:10
  • Hi Martin,
    Deine Fragestellung ist unklar. Wenn eine neue Zeile (neuer Messwert) hinzugefügt wird, dann funktioniert mein Beispiel problemlos.

    Wenn Du einen Messwert änderst, dann muss bei Änderung in der Oberfläche zu diesem Messwert (Zeile) navigiert werden und ein ScrollIntoView entfällt. Wenn eine andere Technologie angewandt wird, dann beschreibe das mal, vor allem das Ereignis, was eine Änderung auslöst und warum Du diese Änderung nicht "fangen" kannst, z.B. mit einem NotifyPropertyChanged, ggf. in einer ObservableCollection.


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


    Montag, 3. Dezember 2018 09:49
  • Also ich geh über Messpunkt

                    Pruefling.Messpunkte.Move(currentID, currentID+1);
                    Pruefling.Messpunkte.Move(currentID+1, currentID);

    mit

                if (e.Action == NotifyCollectionChangedAction.Move)
                {
                    // scroll the new item into view   
                    AssociatedObject.ScrollIntoView(e.OldItems[0]);
                }

    Damit wird die Window79Behavior_CollectionChanged getriggert und das datagrid wird aktualisiert.

    Wahrscheinlich nicht sauber, aber es tut für die Anwendung.

    Danke euch!

    Montag, 3. Dezember 2018 09:51
  • Hi,

    eine ObservableCollection meldet sich in der Tat nur, wenn Items hinzugefügt oder entfernt werden. Wenn du auf eine Änderung von Werten reagieren möchtest, kannst die OCollection erweitern:

        /// <summary>
        /// Implements the "ItemPropertyChanged" Event for a ObservableCollection
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <seealso cref="System.Collections.ObjectModel.ObservableCollection{T}" />
        public sealed class TrulyObservableCollection<T> : ObservableCollection<T>
        where T : INotifyPropertyChanged
        {
            /// <summary>
            /// Initializes a new instance of the <see cref="TrulyObservableCollection{T}"/> class.
            /// </summary>
            public TrulyObservableCollection()
            {
                CollectionChanged += FullObservableCollectionCollectionChanged;
            }
    
            /// <summary>
            /// Initializes a new instance of the <see cref="TrulyObservableCollection{T}"/> class.
            /// </summary>
            /// <param name="pItems">The p items.</param>
            public TrulyObservableCollection(IEnumerable<T> pItems) : this()
            {
                foreach (var item in pItems)
                {
                    this.Add(item);
                }
            }
    
            /// <summary>
            /// Fulls the observable collection collection changed.
            /// </summary>
            /// <param name="sender">The sender.</param>
            /// <param name="e">The <see cref="NotifyCollectionChangedEventArgs"/> instance containing the event data.</param>
            private void FullObservableCollectionCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
            {
                if (e.NewItems != null)
                {
                    foreach (Object item in e.NewItems)
                    {
                        ((INotifyPropertyChanged)item).PropertyChanged += ItemPropertyChanged;
                    }
                }
                if (e.OldItems != null)
                {
                    foreach (Object item in e.OldItems)
                    {
                        ((INotifyPropertyChanged)item).PropertyChanged -= ItemPropertyChanged;
                    }
                }
            }
    
            /// <summary>
            /// Items the property changed.
            /// </summary>
            /// <param name="sender">The sender.</param>
            /// <param name="e">The <see cref="PropertyChangedEventArgs"/> instance containing the event data.</param>
            private void ItemPropertyChanged(object sender, PropertyChangedEventArgs e)
            {
                NotifyCollectionChangedEventArgs args = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, sender, sender, IndexOf((T)sender));
                OnCollectionChanged(args);
            }
        }

    Deine Messpunkte-Collection sieht dann so aus:

    public TrulyObservableCollection<Window79DataM> Messpunkte { get; set; } = new TrulyObservableCollection<Window79DataM>();

    Und dein Behavior so:

        public class Window79Behavior : Behavior<DataGrid>
        {
            protected override void OnAttached() =>
              ((INotifyCollectionChanged)AssociatedObject.Items).CollectionChanged += Window79Behavior_CollectionChanged;
            protected override void OnDetaching() =>
              ((INotifyCollectionChanged)AssociatedObject.Items).CollectionChanged += Window79Behavior_CollectionChanged;
    
            private void Window79Behavior_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
            {
                if (e.Action == NotifyCollectionChangedAction.Add)
                {
                    // scroll the new item into view   
                    AssociatedObject.ScrollIntoView(e.NewItems[0]);
                }
    
                if (e.Action == NotifyCollectionChangedAction.Replace)
                {
                    // scroll the new item into view   
                    AssociatedObject.ScrollIntoView(e.NewItems[0]);
                }
            }
    
        }
    Ich habe dazu die Demo von Peter Fleischer als Grundlage genommen, welche bei mir funktioniert.

    Bei der Beschreibung einer/s Aufgabe/Frage/Problems ist es wirklich wichtig, so viele Details wie möglich zu liefern, da es ansonsten ein Ratespiel ist.

    Gruß


    Freiberufler im Bereich Softwareentwicklung Von der PLC und Robotik zu VB.NET & C#, vorrangig WPF und UWP

    Dienstag, 4. Dezember 2018 10:48