I have a listbox that I am trying to build a triggeraction for. Basically I would like my triggeraction to be triggered when ItemsSource or Items is updated. I tried using both PropertyChangedTrigger and DataStoreChangedTrigger. The problem is that when either of these triggers gets executed my ItemsSource is empty at that time. So the question is what event can I hook into to know when my ItemsSource is changed? I am using the mvvm pattern and therefore cannot have any code behind. Here’s some code
<ListBox x:Name="commentaryViewItems"
VirtualizingStackPanel.IsVirtualizing="False"
Background="White"
ItemsSource="{Binding CommentaryItemViewsModels}">
<iy:Interaction.Triggers>
<is:DataStoreChangedTrigger Binding="{Binding Path=ItemsSource, ElementName=commentaryViewItems}">
<localBehaviors:AutoScrollingTargetedTriggerAction></localBehaviors:AutoScrollingTargetedTriggerAction>
</is:DataStoreChangedTrigger>
</iy:Interaction.Triggers>
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:CommentaryItemView DataContext="{Binding}"></local:CommentaryItemView>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ListBox>
public class AutoScrollingTargetedTriggerAction : TriggerAction<ListBox>
{
protected override void Invoke(object parameter)
{
ListBox items = AssociatedObject as ListBox;
if (items != null)
{
ItemCollection commentaryItemViewModels = items.Items;
if (commentaryItemViewModels != null)
{
IList<ICommentaryItemViewModel> viewModels = new List<ICommentaryItemViewModel>();
foreach (var viewModel in commentaryItemViewModels)
{
ICommentaryItemViewModel currentViewModel = viewModel as ICommentaryItemViewModel;
if (currentViewModel != null)
viewModels.Add(currentViewModel);
}
if (viewModels.Count > 0)
{
// if there is more than one date header go to first one and move scroll to there
if (viewModels.Count(c => c.IsTitleBarVisible == true) > 1)
{
// get first viewmodel with header
ICommentaryItemViewModel viewModel =
viewModels.FirstOrDefault(f => f.IsTitleBarVisible == true);
if (viewModel != null)
items.ScrollIntoView(viewModel.View);
}
// if there is only one header move scroller to last item
if (viewModels.Count(c => c.IsTitleBarVisible == true) == 1)
{
ICommentaryItemViewModel viewModel =
viewModels.FirstOrDefault(f => f.IsTitleBarVisible == true);
if (viewModel != null)
items.ScrollIntoView(viewModel.View);
}
}
}
}
}
}
I was using an observablecollection. The problem is that I’m trying to scroll my listbox based on the items contained within it. So at the time that the observablecollection changes it is not necessarily the time that the listbox has been updated. What I ended up doing is hooking into a click button that I had below and that seems to be occuring at the appropriate time.