A so-called behavior will help you.
It is assumed that your application is called "MyApp".
Then you could implement the wished behavior in a subfolder called Behaviors.
using System.Windows.Controls;
using System.Windows.Interactivity;
namespace MyApp.Behaviors
{
public class ListBoxScrollIntoViewBehavior : Behavior<ListBox>
{
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.SelectionChanged += AssociatedObject_SelectionChanged;
}
private void AssociatedObject_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var listBox = sender as ListBox;
if (listBox?.SelectedItem != null)
{
listBox.Dispatcher.Invoke(() =>
{
listBox.UpdateLayout();
listBox.ScrollIntoView(listBox.SelectedItem);
});
}
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.SelectionChanged -= AssociatedObject_SelectionChanged;
}
}
}
In your XAML you must reference "System.Windows.Interactivity"
and the Behaviors namespace.
<Window x:Class="MyApp.MainWindow"
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:behaviors="clr-namespace:MyApp.Behaviors"
xmlns:local="clr-namespace:MyApp"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<ListBox Name="ListBoxItems">
<i:Interaction.Behaviors>
<behaviors:ListBoxScrollIntoViewBehavior/>
</i:Interaction.Behaviors>
</ListBox>
</Grid>
</Window>
That way there is no need to force the ListBox to scroll down by code behind.
The ListBox will scroll down automatically to the SelectedItem.
The only thing is to set the SelectedItem to the newly added entry as it is shown in this example:
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
namespace MyApp
{
public partial class MainWindow
{
private ObservableCollection<string> items;
public MainWindow()
{
Loaded += MainWindow_Loaded;
InitializeComponent();
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
items = new ObservableCollection<string>
{
"A",
"B",
"B",
"C",
"D"
};
ListBoxItems.ItemsSource = items;
ListBoxItems.SelectedItem = items.LastOrDefault();
}
}
}
Behaviors are also useful in MVVM scenarios where you cannot call control methods from code behind.
See also a more detailed explanation here: https://www.wpftutorial.net/Behaviors.html