The line Resources.Add("eventAggregator", Container.Resolve()); raises Null exception.
UPDATE I've added all classes to explain more. As @Axemasta said, there is no need to register IEventAggregator and I removed registration. Now I don't how to connect the Listview EventAggregator behavior to the EventAggregator.
This is whole App.xaml code file.
public partial class App : PrismApplication
{
/*
* The Xamarin Forms XAML Previewer in Visual Studio uses System.Activator.CreateInstance.
* This imposes a limitation in which the App class must have a default constructor.
* App(IPlatformInitializer initializer = null) cannot be handled by the Activator.
*/
public App() : this(null) { }
public App(IPlatformInitializer initializer) : base(initializer) { }
protected override async void OnInitialized()
{
InitializeComponent();
Resources.Add("eventAggregator", Container.Resolve<IEventAggregator>());// Removed on update
FlowListView.Init();
await NavigationService.NavigateAsync("NavigationPage/MainPage");
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterForNavigation<NavigationPage>();
containerRegistry.RegisterForNavigation<MainPage>();
}
}
}
The behavior class:
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(ListItem 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);
}
}
The Event class:
public class ScrollToMyModelEvent : PubSubEvent<ListItem>
{
}
The page view model:
public MainPageViewModel(INavigationService navigationService, IEventAggregator eventAggregator)
: base (navigationService)
{
Title = "صفحه اصلی";
ListHeight = 100;
ListWidth = 250;
_eventAggregator = eventAggregator;
Items items = new Items();
ListViewItemSouce = items.GetItems();
MyModels = items.GetItems();
SelectedModel = ListViewItemSouce[3];
_eventAggregator.GetEvent<ScrollToMyModelEvent>().Publish(SelectedModel);
}
The page view:
<StackLayout HorizontalOptions="Center" VerticalOptions="Center" WidthRequest="{Binding ListWidth}" HeightRequest="{Binding ListHeight}"
Grid.Row="1" Grid.Column="1">
<local:NativeListView x:Name="lst3" ItemsSource="{Binding ListViewItemSouce}" Margin="1" BackgroundColor="Transparent" RowHeight="47" HasUnevenRows="false">
<ListView.Behaviors>
<local:ScrollToMyModelBehavior EventAggregator="{StaticResource eventAggregator}" /> // Error raised that there is not such a static property
</ListView.Behaviors>
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Word}" TextColor="Black"/>
</DataTemplate>
</ListView.ItemTemplate>
</local:NativeListView>
</StackLayout>
You do not need to register
IEventAggregator
when the app initialises, much likeINavigationService
orIPageDialog
, you can use it straight out of the box!To use
EventAggregator
you should do the following things:Create an Event
You will first need to create an Event (using Prism) that you can pass to the
EventAggregator
. Your event should inherit fromPubSubEvent
, you can pass this an object (optional). So your event would look like this:Looking at a recent app, I most commonly use this when passing data between custom popup views (like a dictionary of params).
Subscribe to the Event
When
IEventAggregator
fires, anything that has subscribe to the event will execute any code specified. In the class you want to recieved the event you will have to do the following:IEventAggregator
through the constructor (prism does the DI afterall)IEventAggregator
for use in this classIEventAggregator
to a handler method.Here is what the code may look like:
Fire the Event
Now you have registered for the event, you can fire the event. Pass the
IEventAggregator
into whatever class you want to fire the event from and use thePublish Method
:Thats the long and the short of it. You could pass anything to the
IEventAggregator
, you would just need to handle for this in the methods you are subscribing.Hopefully that is enough to get you going using
IEventAggregator
!My guidance on this has evolved as features have been added to Prism to make this sort of thing even easier.
In the past the reason you would resolve and add the IEventAggregator as a StaticResource is that there was no way to inject this. We now have the ContainerProvider which amazingly allows you to add types in XAML that require Dependency Injection. To start you can refactor your ScrollToBehavior to use a DI Pattern by adding the
IEventAggregator
as a constructor parameter, removing the Bindable Property (if you choose).As I mentioned you can use the
ContainerProvider
in XAML to resolve and provide a type that requires DI, as follows:Just verify if you are adding below code in IOS, Android and UWP projects.
IOS- Appdelegate
Android - MainActivity
UWP-- MainPage.cs