Reputation: 31
I have a UserList that I want to Reuse on multiple pages in my Xamarin Application, but on each of the different pages a ItemSelected event should do something different.
I know about Bindable properties. I use them to bind a list from my Viewmodel to the Reusable Component. But I don't know how to do this with events
Let me show you some code!
This is the XAML of my Reusable ListView. It contains a list of Users
<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="KineAppForms.Views.ReusableViews.UserTable"
x:Name="this">
<ContentView.Content>
<ListView ItemsSource="{Binding Source={x:Reference this},Path=Users, Mode=TwoWay}">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Name.GivenName}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentView.Content>
</ContentView>
The .cs file where I do the binding looks as follows
namespace KineAppForms.Views.ReusableViews
{
public partial class UserTable : ContentView
{
public ObservableCollection<Patient> Users
{
get
{
return (ObservableCollection<Patient>)GetValue(UsersProperty);
}
set
{
SetValue(UsersProperty, value);
}
}
public static readonly BindableProperty UsersProperty =
BindableProperty.Create("Users", typeof(ObservableCollection<Patient>), typeof(UserTable), null,
BindingMode.Default, null, OnItemsSourceChanged);
static void OnItemsSourceChanged(BindableObject bindable, object oldvalue, object newvalue)
{
System.Diagnostics.Debug.WriteLine("source changed");
}
public UserTable()
{
InitializeComponent();
}
}
}
Now the way how I Use my Reusable Component
<views:UserTable Users="{Binding PatientList ,Mode=TwoWay}" />
The Binding PatientList comes from a ViewModel.
No to conclude the question: How Can I Bind an ItemSelected Event To a Command in a ViewModel.
Say I have 2 pages. 1 page with Patients and 1 page with Doctors. They both use the Same table but the Patients Table should go to a Detailed page of Patients ( Link it to goToPatientDetailCommand in PatientListViewModel) and the doctors table should go to a Detailed Page of a Doctor ( Link it to goToPatientDetailCommand in DoctorListViewModel)
It should be something like this
<views:UserTable Users="{Binding PatientList ,Mode=TwoWay}" OnItemSelected="{Binding GoToPatientDetailed, Mode=TwoWay }/>
or
<views:UserTable Users="{Binding DoctorList ,Mode=TwoWay}" OnItemSelected="{Binding GoToDoctorDetailed, Mode=TwoWay }/>
Thank you!
Upvotes: 0
Views: 455
Reputation: 597
There are several approaches in here.
ItemSelectedCommand
to UserTable class public partial class UserTable : ContentView
{
public ObservableCollection<Patient> Users
{
get
{
return (ObservableCollection<Patient>)GetValue(UsersProperty);
}
set
{
SetValue(UsersProperty, value);
}
}
public static readonly BindableProperty UsersProperty =
BindableProperty.Create("Users", typeof(ObservableCollection<Patient>), typeof(UserTable), null,
BindingMode.Default, null, OnItemsSourceChanged);
public static BindableProperty ItemSelectedCommandProperty = BindableProperty.Create(
propertyName: nameof(ItemSelectedCommand),
returnType: typeof(ICommand),
declaringType: typeof(UserTable),
defaultValue: null);
public ICommand ItemSelectedCommand
{
get { return (ICommand)GetValue(ItemSelectedCommandProperty); }
set { SetValue(ItemSelectedCommandProperty, value); }
}
static void OnItemsSourceChanged(BindableObject bindable, object oldvalue, object newvalue)
{
System.Diagnostics.Debug.WriteLine("source changed");
}
public UserTable()
{
InitializeComponent();
}
}
Then in Xaml you can either use EventToCommandBehaviour by adding
<ListView.Behaviors>
<behaviors:EventToCommandBehavior EventName="ItemSelected" Command="{Binding Source={x:Reference this},Path=ItemSelectedCommand}"/>
</ListView.Behaviors>
or you can create your own CustomListView
(that inherites from ListView) that has ItemSelected in it like in this example
ListView
you can create a data template. Here you have documentation on how to do it. If you ask for my opinion, I would say go with second approach - later you can reuse that View in other places.
Upvotes: 1