Reputation: 301
I have xamarin forms app which uses prism. I'm using a ListView
which is bound to an ObservableCollection<string>
, however whenever the listview opens again , it needs to scroll to previously selected item from the listview.
There is a method ScrollTo but how would I implement it using prism?
Could you please help me out with this issue?
<ListView ItemsSource="{Binding obsCommonList}" HasUnevenRows="True" BackgroundColor="Black" SeparatorVisibility="None" SelectedItem="{Binding SelectedProp,Mode=TwoWay}">
<ListView.Behaviors>
<b:EventToCommandBehavior EventName="ItemTapped" Command="{Binding ItemTappedCommand}" EventArgsParameterPath="Item"/>
</ListView.Behaviors>
Upvotes: 0
Views: 1342
Reputation: 5799
You might try something like the following:
Start with making the EventAggregator available in the resources so that you can add this to a behavior property in your XAML.
public class App : PrismApplication
{
protected override async void OnInitialized()
{
Resources.Add("eventAggregator", Container.Resolve<IEventAggregator>());
await NavigationService.NavigateAsync("MainPage");
}
}
Create an event that takes the model type that you have in your ObservableCollection
public class ScrollToMyModelEvent : PubSubEvent<MyModel>
{
}
Add a Behavior with a property for the IEventAggregator. NOTE You don't need the property to be a Bindable Property, or really observable. What you really need is to make sure you subscribe to the event when the EventAggregator is set.
public class ScrollToMyModelBehavior : BehaviorBase<ListView>
{
private IEventAggregator _eventAggregator;
public IEventAggregator EventAggregator
{
get => _eventAggregator;
set
{
if(!EqualityComparer<IEventAggregator>.Default.Equals(_eventAggregator, value))
{
_eventAggregator = value;
_eventAggregator.GetEvent<ScrollToMyModelEvent>().Subscribe(OnScrollToEventPublished);
}
}
}
private void OnScrollToEventPublished(MyModel model)
{
AssociatedObject.ScrollTo(model, ScrollToPosition.Start, true);
}
protected override void OnDetachingFrom(ListView bindable)
{
base.OnDetachingFrom(bindable);
// The Event Aggregator uses weak references so forgetting to do this
// shouldn't create a problem, but it is a better practice.
EventAggregator.GetEvent<ScrollToMyModelEvent>().Unsubscribe(OnScrollToEventPublished);
}
}
In your ViewModel, you now simply need to publish the event. You can do as I show here where you only do this when you Navigate Back to the View. This would then be handled in the Behavior and pass it into the ListView's ScrollTo method.
public class MyListPageViewModel : BindableBase, INavigatedAware
{
private IEventAggregator _eventAggregator { get; }
public MyListPageViewModel(IEventAggregator eventAggregator)
{
_eventAggregator = eventAggregator;
}
public ObservableCollection<MyModel> MyModels { get; set; }
public MyModel SelectedModel { get; set; }
public void OnNavigatedTo(NavigationParameters)
{
if(parameters.GetNavigationMode() == NavigationMode.Back &&
SelectedModel != null)
{
_eventAggregator.GetEvent<ScrollToMyModelEvent>()
.Publish(SelectedModel);
}
}
}
Then in your View
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:behavior="clr-namespace:AwesomeApp.Behaviors"
x:Class="AwesomeApp.ScrollToPage">
<ListView>
<ListView.Behaviors>
<behavior:ScrollToMyModelBehavior EventAggregator="{StaticResource eventAggregator}" />
</ListView.Behaviors>
</ListView>
</ContentPage>
Upvotes: 2