How to bind ItemSource using Reactive MVVM in Xamarin.Forms Accordion (SfAccordion)
The SfAccordion allows you to bind ItemSource to the reactive UI ViewModel which is a composable and cross-platform model-view-viewmodel framework for all .NET platforms.
To achieve this, follow the below steps:
STEP 1: Install the ReactiveUI and ReactiveUI.XamForms in your project.
STEP 2: Create ViewModel which should implement ReactiveObject.
public class ViewModel : ReactiveObject
{
private ObservableCollection<ContactInfo> contacts;
#region Properties
public ObservableCollection<ContactInfo> Contacts
{
get
{
return this.contacts;
}
set
{
this.RaiseAndSetIfChanged(ref contacts, value);
}
}
public Command<object> TapCommand { get; set; }
#endregion
#region Constructor
public ViewModel()
{
Contacts = new ObservableCollection<ContactInfo>();
TapCommand = new Command<object>(OnTapped);
Contacts.Add(new ContactInfo() { Type = "A", Contacts = new ObservableCollection<Contact>() { new Contact() { ContactName = "Adam" }, new Contact { ContactName = "Aaron" } } });
Contacts.Add(new ContactInfo() { Type = "B", Contacts = new ObservableCollection<Contact>() { new Contact() { ContactName = "Bolt" }, new Contact { ContactName = "Bush" } } });
Contacts.Add(new ContactInfo() { Type = "C", Contacts = new ObservableCollection<Contact>() { new Contact() { ContactName = "Clark" }, new Contact { ContactName = "Clara" } } });
}
#endregion
#region Private Methods
private void OnTapped(object obj)
{
var data = obj as Contact;
App.Current.MainPage.DisplayAlert("Message", "Tapped Accoridon item is : " + data.ContactName, "Ok");
}
#endregion
}
STEP 3: ContentPage should inherit from ReactiveContentPage<TViewModel> and we are going to use ReactiveUI Binding to bind our ViewModel to our View.
XMAL
public partial class MainPage : ReactiveContentPage<ViewModel>
{
public MainPage(ViewModel viewModel)
{
}
}
C#
<?xml version="1.0" encoding="utf-8" ?>
<rxui:ReactiveContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:AccordionXamarin"
xmlns:rxui="clr-namespace:ReactiveUI.XamForms;assembly=ReactiveUI.XamForms"
xmlns:syncfusion="clr-namespace:Syncfusion.XForms.Accordion;assembly=Syncfusion.Expander.XForms"
xmlns:sflistview="clr-namespace:Syncfusion.ListView.XForms;assembly=Syncfusion.SfListView.XForms"
x:Class="AccordionXamarin.MainPage"
x:TypeArguments="local:ViewModel" >
<ContentPage.Content>
<StackLayout>
<syncfusion:SfAccordion x:Name="Accordion" BindableLayout.ItemsSource="{Binding Contacts}" ExpandMode="SingleOrNone" >
<BindableLayout.ItemTemplate>
<DataTemplate>
<syncfusion:AccordionItem >
<syncfusion:AccordionItem.Header >
<Grid HeightRequest="60">
<Label Text="{Binding Type}" BackgroundColor="Aqua" VerticalTextAlignment="Center" HorizontalTextAlignment="Center"/>
</Grid>
</syncfusion:AccordionItem.Header>
<syncfusion:AccordionItem.Content>
<Grid x:Name="mainGrid" Padding="4" HeightRequest="135" >
<sflistview:SfListView AllowGroupExpandCollapse="True" IsScrollingEnabled="False" x:Name="listView" IsScrollBarVisible="False" AutoFitMode="DynamicHeight"
ItemSpacing="3" ItemsSource="{Binding Contacts}" >
<sflistview:SfListView.ItemTemplate>
<DataTemplate>
<Grid HeightRequest="60" Padding="1" >
<Label Text="{Binding ContactName}" BackgroundColor="LightBlue"/>
<Grid.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Path=BindingContext.TapCommand, Source={x:Reference Accordion}}" CommandParameter="{Binding .}" />
</Grid.GestureRecognizers>
</Grid>
</DataTemplate>
</sflistview:SfListView.ItemTemplate>
</sflistview:SfListView>
</Grid>
</syncfusion:AccordionItem.Content>
</syncfusion:AccordionItem>
</DataTemplate>
</BindableLayout.ItemTemplate>
</syncfusion:SfAccordion>
</StackLayout>
</ContentPage.Content>
</rxui:ReactiveContentPage>
STEP 4: View can be connected in one-way dependent manner to the ViewModel through bindings. You can set the BindingContext for the SfAccordion in MainPage.cs itself in code behind like below.
public partial class MainPage : ReactiveContentPage<ViewModel>
{
public MainPage(ViewModel viewModel)
{
ViewModel = viewModel;
InitializeComponent();
}
}