Category / Section
How to bind ItemSource using Reactive MVVM in Xamarin.Forms Accordion (SfAccordion)
2 mins read
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(); } }