Category / Section
How to bind data using Reactive MVVM in Xamarin.Forms TreeView (SfTreeView)
7 mins read
The SfTreeView allows you to bind ItemTemplate 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 { #region Fields private ObservableCollection<FileManager> imageNodeInfo; #endregion #region Constructor public ViewModel() { GenerateSource(); } #endregion #region Properties public ObservableCollection<FileManager> ImageNodeInfo { get { return imageNodeInfo; } set { this.RaiseAndSetIfChanged(ref imageNodeInfo, value); } } #endregion #region Generate Source private void GenerateSource() { var nodeImageInfo = new ObservableCollection<FileManager>(); Assembly assembly = typeof(MainPage).GetTypeInfo().Assembly; var doc = new FileManager() { ItemName = "Documents", ImageIcon = ImageSource.FromResource("TreeViewXamarin.Icons.treeview_folder.png", assembly) }; var download = new FileManager() { ItemName = "Downloads", ImageIcon = ImageSource.FromResource("TreeViewXamarin.Icons.treeview_folder.png", assembly) }; var mp3 = new FileManager() { ItemName = "Music", ImageIcon = ImageSource.FromResource("TreeViewXamarin.Icons.treeview_folder.png", assembly) }; var pictures = new FileManager() { ItemName = "Pictures", ImageIcon = ImageSource.FromResource("TreeViewXamarin.Icons.treeview_folder.png", assembly) }; var video = new FileManager() { ItemName = "Videos", ImageIcon = ImageSource.FromResource("TreeViewXamarin.Icons.treeview_folder.png", assembly) }; var pollution = new FileManager() { ItemName = "Environmental Pollution.docx", ImageIcon = ImageSource.FromResource("TreeViewXamarin.Icons.treeview_word.png", assembly) }; var globalWarming = new FileManager() { ItemName = "Global Warming.ppt", ImageIcon = ImageSource.FromResource("TreeViewXamarin.Icons.treeview_ppt.png", assembly) }; var sanitation = new FileManager() { ItemName = "Sanitation.docx", ImageIcon = ImageSource.FromResource("TreeViewXamarin.Icons.treeview_word.png", assembly) }; var socialNetwork = new FileManager() { ItemName = "Social Network.pdf", ImageIcon = ImageSource.FromResource("TreeViewXamarin.Icons.treeview_pdf.png", assembly) }; var youthEmpower = new FileManager() { ItemName = "Youth Empowerment.pdf", ImageIcon = ImageSource.FromResource("TreeViewXamarin.Icons.treeview_pdf.png", assembly) }; var games = new FileManager() { ItemName = "Game.exe", ImageIcon = ImageSource.FromResource("TreeViewXamarin.Icons.treeview_exe.png", assembly) }; var tutorials = new FileManager() { ItemName = "Tutorials.zip", ImageIcon = ImageSource.FromResource("TreeViewXamarin.Icons.treeview_zip.png", assembly) }; var typeScript = new FileManager() { ItemName = "TypeScript.7z", ImageIcon = ImageSource.FromResource("TreeViewXamarin.Icons.treeview_zip.png", assembly) }; var uiGuide = new FileManager() { ItemName = "UI-Guide.pdf", ImageIcon = ImageSource.FromResource("TreeViewXamarin.Icons.treeview_pdf.png", assembly) }; var song = new FileManager() { ItemName = "Gouttes", ImageIcon = ImageSource.FromResource("TreeViewXamarin.Icons.treeview_mp3.png", assembly) }; var camera = new FileManager() { ItemName = "Camera Roll", ImageIcon = ImageSource.FromResource("TreeViewXamarin.Icons.treeview_folder.png", assembly) }; var stone = new FileManager() { ItemName = "Stone.jpg", ImageIcon = ImageSource.FromResource("TreeViewXamarin.Icons.treeview_png.png", assembly) }; var wind = new FileManager() { ItemName = "Wind.jpg", ImageIcon = ImageSource.FromResource("TreeViewXamarin.Icons.treeview_png.png", assembly) }; var img0 = new FileManager() { ItemName = "WIN_20160726_094117.JPG", ImageIcon = ImageSource.FromResource("TreeViewXamarin.Icons.treeview_img0.png", assembly) }; var img1 = new FileManager() { ItemName = "WIN_20160726_094118.JPG", ImageIcon = ImageSource.FromResource("TreeViewXamarin.Icons.treeview_img1.png", assembly) }; var video1 = new FileManager() { ItemName = "Naturals.mp4", ImageIcon = ImageSource.FromResource("TreeViewXamarin.Icons.treeview_video.png", assembly) }; var video2 = new FileManager() { ItemName = "Wild.mpeg", ImageIcon = ImageSource.FromResource("TreeViewXamarin.Icons.treeview_video.png", assembly) }; doc.SubFiles = new ObservableCollection<FileManager> { pollution, globalWarming, sanitation, socialNetwork, youthEmpower }; download.SubFiles = new ObservableCollection<FileManager> { games, tutorials, typeScript, uiGuide }; mp3.SubFiles = new ObservableCollection<FileManager> { song }; pictures.SubFiles = new ObservableCollection<FileManager> { camera, stone, wind }; camera.SubFiles = new ObservableCollection<FileManager> { img0, img1 }; video.SubFiles = new ObservableCollection<FileManager> { video1, video2 }; nodeImageInfo.Add(doc); nodeImageInfo.Add(download); nodeImageInfo.Add(mp3); nodeImageInfo.Add(pictures); nodeImageInfo.Add(video); imageNodeInfo = nodeImageInfo; } #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#
<rxui:ReactiveContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:rxui="clr-namespace:ReactiveUI.XamForms;assembly=ReactiveUI.XamForms" xmlns:local="clr-namespace:TreeViewXamarin" xmlns:syncfusion="clr-namespace:Syncfusion.XForms.TreeView;assembly=Syncfusion.SfTreeView.XForms" x:Class="TreeViewXamarin.MainPage" x:TypeArguments="local:ViewModel"> <ContentPage.Content> <syncfusion:SfTreeView x:Name="treeView" ItemHeight="40" Indentation="15" ExpanderWidth="40" ChildPropertyName="SubFiles" ItemTemplateContextType="Node" ItemsSource="{Binding ImageNodeInfo}" > <syncfusion:SfTreeView.ItemTemplate> <DataTemplate> <Grid x:Name="grid" RowSpacing="0" > <Grid.RowDefinitions> <RowDefinition Height="*" /> <RowDefinition Height="1" /> </Grid.RowDefinitions> <Grid RowSpacing="0" Grid.Row="0"> <Grid.ColumnDefinitions> <ColumnDefinition Width="40" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <Grid Padding="5,5,5,5"> <Image Source="{Binding Content.ImageIcon}" VerticalOptions="Center" HorizontalOptions="Center" HeightRequest="35" WidthRequest="35"/> </Grid> <Grid Grid.Column="1" RowSpacing="1" Padding="1,0,0,0" VerticalOptions="Center"> <Label LineBreakMode="NoWrap" Text="{Binding Content.ItemName}" VerticalTextAlignment="Center"> </Label> </Grid> </Grid> <StackLayout Grid.Row="1"/> </Grid> </DataTemplate> </syncfusion:SfTreeView.ItemTemplate> </syncfusion:SfTreeView> </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 SfTreeView in MainPage.cs itself in code behind like below.
public partial class MainPage : ReactiveContentPage<ViewModel> { public MainPage(ViewModel viewModel) { ViewModel = viewModel; InitializeComponent(); } }