1

I have a ComboBox which uses ListBox to show items. ListBox’s ItemSource is bound with a CollectionViewSource.

Issue: Once I open ComboBox and scroll through the items and leave it in middle or at bottom. Once I reopen ComboBox, even though I refresh or reload ItemSource (CollectionViewSource), the Scrollbar remains at the same place where I left it last time. I want it to be as default (at top) each and every time I reload ItemSource.

Is there is any way of doing this in XAML itself? Another thing, I cannot use Behavior or Attach property. I want any template or style for this.

A K P
  • 81
  • 1
  • 9

1 Answers1

1

In order for a Style on a ListBox to embody some behavior for the <ScrollViewer>, you would need to use an Attached Property / Attached Behavior to control the ScrollViewer's "grabber" position. This is because your collection is bound to your ListBox and notifying when it is updated needs to drive a behavior that isn't natively on the ListBox. It may be possible to reset the scroll position with a <ControlTemplate> for the <ScrollViewer> itself, but I imagine it would be difficult as it would likely involve manipulating Transforms / StoryBoards based on DataTriggering with your ItemsSource, but again that may cause a dependency on needing to use an Attached property, which for some reason you can't use...

If you simply want to get a result now, and you don't care about testability or re-usability, I would handle the TargetUpdated event in the code-behind. It's ultimately what the Attached Behavior would end up doing. On the other hand, if you do care about re-usability then you need to evaluate and challenge why you can't use an Attached Behavior (they are also testable, too); an Attached Behavior would be also easier than trying to edit a ControlTemplate.

Here is the code-behind approach:

.xaml:

<ListBox x:Name="myListBox" 
        ItemsSource="{Binding MyItemsSource, NotifyOnTargetUpdated=True}"
        TargetUpdated="ListBox_TargetUpdated"/>

.xaml.cs:

private void ListBox_TargetUpdated(object sender, DataTransferEventArgs e)
{
    if (myListBox.Items.Count > 0)
        myListBox.ScrollIntoView(myListBox.Items[0]);
}

Edit: On the flip-side, if you are using MVVM, you can do something like this SO post suggests and set IsSynchronizationWithCurrentItem="True" and when you refresh your ItemsSource, simply set your SelectedItem to the first in the list and handle the SelectionChanged event in your vm.

Community
  • 1
  • 1
Isaiah Nelson
  • 2,450
  • 4
  • 34
  • 53