Same with the subject, When i add some item in ListBox, also Listbox's Scroll Bar is moved automatically.
Because verticalOffset is same, but ExtraHeight is enlarged.
I Just want Don't move scrollBar when i insert some item...
I use both of ObservableCollection's Insert(0, Object) method and Add() method
The Symptom appears when VerticalOffSet is not 0 nor max Height. You can see that like below
And i already moved it manually(with Code) But when i move it original position, I should watch the move animation.
Did you have an idea?
Plz know me about that.
In WPF the ItemsControl
maintains the scroll offset relative to the beginning of the list, forcing items in the viewport to move down when items are added to the ItemsSource
. UWP allows to customize this behavior e.g. to behave the way you need it.
I recommend to extend ListBox
or alternatively create an attached behavior.
The following example extends ListBox
and handles the internal ScrollViewer
to adjust the scroll offset to keep the first visible item in the viewport when items are added to the ItemsSource:
class KeepItemsInViewListBox : ListBox
{
private ScrollViewer ScrollViewer { get; set; }
#region Overrides of FrameworkElement
/// <inheritdoc />
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
if (TryFindVisualChildElement(this, out ScrollViewer scrollViewer))
{
this.ScrollViewer = scrollViewer;
}
}
#endregion
#region Overrides of ListView
/// <inheritdoc />
protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)
{
base.OnItemsChanged(e);
if (this.ScrollViewer == null)
{
return;
}
double verticalOffset;
switch (e.Action)
{
case NotifyCollectionChangedAction.Add when e.NewItems != null:
// Check if insert or add
verticalOffset = e.NewStartingIndex < this.ScrollViewer.VerticalOffset
? this.ScrollViewer.VerticalOffset + e.NewItems.Count
: this.ScrollViewer.VerticalOffset;
break;
case NotifyCollectionChangedAction.Remove when e.OldItems != null:
verticalOffset = this.ScrollViewer.VerticalOffset - e.OldItems.Count;
break;
default:
verticalOffset = this.ScrollViewer.VerticalOffset;
break;
}
this.ScrollViewer?.ScrollToVerticalOffset(verticalOffset);
}
#endregion
public bool TryFindVisualChildElement<TChild>(DependencyObject parent, out TChild childElement)
where TChild : FrameworkElement
{
childElement = null;
if (parent == null)
{
return false;
}
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(parent, i);
if (child is TChild resultElement)
{
childElement = resultElement;
return true;
}
if (TryFindVisualChildElement(child, out childElement))
{
return true;
}
}
return false;
}
}
The class can be enhanced by making the behavior optional e.g., by introducing an enum.