Skip to content

Commit a0a766d

Browse files
Merge pull request #1 from SyncfusionExamples/Sample
Added sample for the KB
2 parents c2b9569 + d22cc60 commit a0a766d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+9469
-2
lines changed

README.md

Lines changed: 245 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,245 @@
1-
# How-to-use-DataTemplateSelector-with-ContentItemTemplate-in-.NET-MAUI-TabView
2-
Block Editor component repository This repository contains a sample explaining how to use DataTemplateSelector with ContentItemTemplate in .NET MAUI TabView.
1+
This article provides a comprehensive guide on utilizing a `DataTemplateSelector` with the [ContentItemTemplate](https://help.syncfusion.com/cr/maui/Syncfusion.Maui.TabView.SfTabView.html#Syncfusion_Maui_TabView_SfTabView_ContentItemTemplate) property in the [.NET MAUI TabView](https://www.syncfusion.com/maui-controls/maui-tab-view) control.
2+
3+
By following the steps below, you can create a flexible tab view that supports varying content for each tab based on its associated data model.
4+
5+
**Step 1:** Create a CustomSfTabView
6+
7+
- Extend the TabView control to add a `ContentItemTemplateSelector` property.
8+
- Handle the [SelectionChanged](https://help.syncfusion.com/cr/maui/Syncfusion.Maui.TabView.SfTabView.html?tabs=tabid-1#Syncfusion_Maui_TabView_SfTabView_SelectionChanged) and `Loaded` events to dynamically set the content template.
9+
10+
```
11+
public class CustomSfTabView : SfTabView
12+
{
13+
// Dependency property for ItemTemplateSelector
14+
public static readonly BindableProperty ContentItemTemplateSelectorProperty =
15+
BindableProperty.Create(
16+
nameof(ContentItemTemplateSelector),
17+
typeof(DataTemplateSelector),
18+
typeof(CustomSfTabView),
19+
null,
20+
propertyChanged: OnContentItemTemplateSelectorChanged);
21+
22+
// Property wrapper
23+
public DataTemplateSelector ContentItemTemplateSelector
24+
{
25+
get => (DataTemplateSelector)GetValue(ContentItemTemplateSelectorProperty);
26+
set => SetValue(ContentItemTemplateSelectorProperty, value);
27+
}
28+
29+
// Handle changes to the template selector
30+
private static void OnContentItemTemplateSelectorChanged(BindableObject bindable, object oldValue, object newValue)
31+
{
32+
var tabView = bindable as CustomSfTabView;
33+
if (tabView != null)
34+
{
35+
tabView.SetInitialTemplate();
36+
}
37+
}
38+
39+
// Constructor
40+
public CustomSfTabView()
41+
{
42+
// Wire up selection changed event
43+
SelectionChanged += OnSelectionChanged;
44+
Loaded += OnLoaded;
45+
}
46+
47+
// Loaded event handler
48+
private void OnLoaded(object? sender, EventArgs e)
49+
{
50+
SetInitialTemplate();
51+
}
52+
53+
// Selection changed handler
54+
private void OnSelectionChanged(object? sender, TabSelectionChangedEventArgs e)
55+
{
56+
if (e.NewIndex != -1 && ItemsSource != null && ContentItemTemplateSelector != null)
57+
{
58+
var selectedItem = ItemsSource.Cast<object>().ElementAt((Index)e.NewIndex);
59+
HandleTabSelection(selectedItem);
60+
}
61+
}
62+
63+
// Method to set initial template
64+
private void SetInitialTemplate()
65+
{
66+
// Ensure both ItemsSource and ContentItemTemplateSelector are available
67+
if (ItemsSource != null && ContentItemTemplateSelector != null)
68+
{
69+
// Try to get the first item
70+
var items = ItemsSource.Cast<object>().ToList();
71+
if (items.Any())
72+
{
73+
var firstItem = items.First();
74+
75+
// Select template for the first item
76+
var selectedTemplate = ContentItemTemplateSelector.SelectTemplate(firstItem, this);
77+
78+
// Directly set the ContentItemTemplate
79+
ContentItemTemplate = selectedTemplate;
80+
81+
// Optional: Log for debugging
82+
System.Diagnostics.Debug.WriteLine($"Initial template set for item type: {firstItem?.GetType()}");
83+
}
84+
}
85+
}
86+
// Dynamic template selection method
87+
private void HandleTabSelection(object selectedItem)
88+
{
89+
// Directly use the ContentItemTemplateSelector if available
90+
if (ContentItemTemplateSelector != null)
91+
{
92+
ContentItemTemplate = ContentItemTemplateSelector.SelectTemplate(selectedItem, this);
93+
}
94+
}
95+
}
96+
```
97+
98+
**Step 2:** Create a DataTemplateSelector
99+
100+
- Implement a class that inherits from `DataTemplateSelector`.
101+
- Define templates and logic to select the appropriate one based on the data type.
102+
103+
```
104+
public class TabItemTemplateSelector : DataTemplateSelector
105+
{
106+
public DataTemplate? TextTemplate { get; set; }
107+
public DataTemplate? ImageTemplate { get; set; }
108+
public DataTemplate? ComplexTemplate { get; set; }
109+
110+
protected override DataTemplate? OnSelectTemplate(object item, BindableObject container)
111+
{
112+
return item switch
113+
{
114+
TextTabItem => TextTemplate,
115+
ImageTabItem => ImageTemplate,
116+
ComplexTabItem => ComplexTemplate,
117+
_ => null
118+
};
119+
}
120+
}
121+
```
122+
123+
**Step 3:** Define Data Models
124+
125+
- Create data models to represent the different types of content that need to be displayed in the TabView.
126+
127+
```
128+
public abstract class BaseTabItem
129+
{
130+
public string? Title { get; set; }
131+
}
132+
133+
public class TextTabItem:BaseTabItem
134+
{
135+
public string? Content { get; set; }
136+
}
137+
138+
//Implement other data models.
139+
```
140+
141+
**Step 5:** ViewModel
142+
143+
- Create a view model to provide the items for the tabs and bind it to your view.
144+
145+
```
146+
public class TabViewViewModel
147+
{
148+
public List<BaseTabItem> TabItems { get; set; }
149+
150+
public TabViewViewModel()
151+
{
152+
TabItems = new List<BaseTabItem>
153+
{
154+
new TextTabItem
155+
{
156+
Title = "Text Tab",
157+
Content = "This is a text tab content"
158+
},
159+
new ImageTabItem
160+
{
161+
Title = "Image Tab",
162+
ImageSource = "dotnet_bot.png"
163+
},
164+
new ComplexTabItem
165+
{
166+
Title = "Complex Tab",
167+
DetailedContent = new {
168+
Name = "Complex Content",
169+
Description = "Detailed information"
170+
}
171+
}
172+
};
173+
}
174+
}
175+
```
176+
177+
**Step 4:** XAML
178+
179+
- Define templates for each data model type in the ResourceDictionary.
180+
- Assign the TabItemTemplateSelector and templates in XAML.
181+
- Bind the CustomSfTabView to the ItemsSource and set the ContentItemTemplateSelector.
182+
183+
```
184+
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
185+
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
186+
x:Class="TabViewItemsSource.MainPage"
187+
xmlns:local="clr-namespace:TabViewItemsSource"
188+
xmlns:tabView="clr-namespace:Syncfusion.Maui.TabView;assembly=Syncfusion.Maui.TabView">
189+
190+
<ContentPage.BindingContext>
191+
<local:TabViewViewModel/>
192+
</ContentPage.BindingContext>
193+
194+
<ContentPage.Resources>
195+
<ResourceDictionary>
196+
<local:TabItemTemplateSelector x:Key="TabItemSelector">
197+
<local:TabItemTemplateSelector.TextTemplate>
198+
<DataTemplate>
199+
<Label Text="{Binding Content}"/>
200+
</DataTemplate>
201+
</local:TabItemTemplateSelector.TextTemplate>
202+
203+
<local:TabItemTemplateSelector.ImageTemplate>
204+
<DataTemplate>
205+
<Image Source="{Binding ImageSource}" />
206+
</DataTemplate>
207+
</local:TabItemTemplateSelector.ImageTemplate>
208+
209+
<local:TabItemTemplateSelector.ComplexTemplate>
210+
<DataTemplate>
211+
<StackLayout >
212+
<Label Text="{Binding DetailedContent.Name}" />
213+
<Label Text="{Binding DetailedContent.Description}" />
214+
</StackLayout>
215+
</DataTemplate>
216+
</local:TabItemTemplateSelector.ComplexTemplate>
217+
</local:TabItemTemplateSelector>
218+
<DataTemplate x:Key="headerItemTemplate">
219+
<StackLayout Margin="10">
220+
<Label Text="{Binding Title}" VerticalOptions="Center"/>
221+
</StackLayout>
222+
</DataTemplate>
223+
</ResourceDictionary>
224+
</ContentPage.Resources>
225+
226+
<local:CustomSfTabView ItemsSource="{Binding TabItems}"
227+
HeaderItemTemplate="{StaticResource headerItemTemplate}"
228+
ContentItemTemplateSelector="{StaticResource TabItemSelector}">
229+
</local:CustomSfTabView>
230+
</ContentPage>
231+
```
232+
233+
**Output**
234+
235+
![TabViewItemsSource.gif](https://support.syncfusion.com/kb/agent/attachment/article/18738/inline?token=eyJhbGciOiJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGRzaWctbW9yZSNobWFjLXNoYTI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjM0NTE0Iiwib3JnaWQiOiIzIiwiaXNzIjoic3VwcG9ydC5zeW5jZnVzaW9uLmNvbSJ9.QmyNTiwaVaoxcQlQK4vwaXG7FyceJF5ZBuicrry2ghY)
236+
237+
**Requirements to run the demo**
238+
239+
To run the demo, refer to [System Requirements for .NET MAUI](https://help.syncfusion.com/maui/system-requirements)
240+
241+
**Troubleshooting:**
242+
243+
**Path too long exception**
244+
245+
If you are facing path too long exception when building this example project, close Visual Studio and rename the repository to short and build the project.

TabViewItemsSource/App.xaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version = "1.0" encoding = "UTF-8" ?>
2+
<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
3+
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
4+
xmlns:local="clr-namespace:TabViewItemsSource"
5+
x:Class="TabViewItemsSource.App">
6+
<Application.Resources>
7+
<ResourceDictionary>
8+
<ResourceDictionary.MergedDictionaries>
9+
<ResourceDictionary Source="Resources/Styles/Colors.xaml" />
10+
<ResourceDictionary Source="Resources/Styles/Styles.xaml" />
11+
</ResourceDictionary.MergedDictionaries>
12+
</ResourceDictionary>
13+
</Application.Resources>
14+
</Application>

TabViewItemsSource/App.xaml.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
namespace TabViewItemsSource
2+
{
3+
public partial class App : Application
4+
{
5+
public App()
6+
{
7+
InitializeComponent();
8+
}
9+
10+
protected override Window CreateWindow(IActivationState? activationState)
11+
{
12+
return new Window(new AppShell());
13+
}
14+
}
15+
}

TabViewItemsSource/AppShell.xaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<Shell
3+
x:Class="TabViewItemsSource.AppShell"
4+
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
5+
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
6+
xmlns:local="clr-namespace:TabViewItemsSource"
7+
Shell.FlyoutBehavior="Flyout"
8+
Title="TabViewItemsSource">
9+
10+
<ShellContent
11+
Title="Home"
12+
ContentTemplate="{DataTemplate local:MainPage}"
13+
Route="MainPage" />
14+
15+
</Shell>

TabViewItemsSource/AppShell.xaml.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace TabViewItemsSource
2+
{
3+
public partial class AppShell : Shell
4+
{
5+
public AppShell()
6+
{
7+
InitializeComponent();
8+
}
9+
}
10+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
using Syncfusion.Maui.TabView;
2+
3+
namespace TabViewItemsSource
4+
{
5+
public class CustomSfTabView : SfTabView
6+
{
7+
// Dependency property for ItemTemplateSelector
8+
public static readonly BindableProperty ContentItemTemplateSelectorProperty =
9+
BindableProperty.Create(
10+
nameof(ContentItemTemplateSelector),
11+
typeof(DataTemplateSelector),
12+
typeof(CustomSfTabView),
13+
null,
14+
propertyChanged: OnContentItemTemplateSelectorChanged);
15+
16+
// Property wrapper
17+
public DataTemplateSelector ContentItemTemplateSelector
18+
{
19+
get => (DataTemplateSelector)GetValue(ContentItemTemplateSelectorProperty);
20+
set => SetValue(ContentItemTemplateSelectorProperty, value);
21+
}
22+
23+
// Handle changes to the template selector
24+
private static void OnContentItemTemplateSelectorChanged(BindableObject bindable, object oldValue, object newValue)
25+
{
26+
var tabView = bindable as CustomSfTabView;
27+
if (tabView != null)
28+
{
29+
tabView.SetInitialTemplate();
30+
}
31+
}
32+
33+
// Constructor
34+
public CustomSfTabView()
35+
{
36+
// Wire up selection changed event
37+
SelectionChanged += OnSelectionChanged;
38+
Loaded += OnLoaded;
39+
}
40+
41+
// Loaded event handler
42+
private void OnLoaded(object? sender, EventArgs e)
43+
{
44+
SetInitialTemplate();
45+
}
46+
47+
// Selection changed handler
48+
private void OnSelectionChanged(object? sender, TabSelectionChangedEventArgs e)
49+
{
50+
if (e.NewIndex != -1 && ItemsSource != null && ContentItemTemplateSelector != null)
51+
{
52+
var selectedItem = ItemsSource.Cast<object>().ElementAt((Index)e.NewIndex);
53+
HandleTabSelection(selectedItem);
54+
}
55+
}
56+
57+
// Method to set initial template
58+
private void SetInitialTemplate()
59+
{
60+
// Ensure both ItemsSource and ContentItemTemplateSelector are available
61+
if (ItemsSource != null && ContentItemTemplateSelector != null)
62+
{
63+
// Try to get the first item
64+
var items = ItemsSource.Cast<object>().ToList();
65+
if (items.Any())
66+
{
67+
var firstItem = items.First();
68+
69+
// Select template for the first item
70+
var selectedTemplate = ContentItemTemplateSelector.SelectTemplate(firstItem, this);
71+
72+
// Directly set the ContentItemTemplate
73+
ContentItemTemplate = selectedTemplate;
74+
75+
// Optional: Log for debugging
76+
System.Diagnostics.Debug.WriteLine($"Initial template set for item type: {firstItem?.GetType()}");
77+
}
78+
}
79+
}
80+
// Dynamic template selection method
81+
private void HandleTabSelection(object selectedItem)
82+
{
83+
// Directly use the ContentItemTemplateSelector if available
84+
if (ContentItemTemplateSelector != null)
85+
{
86+
ContentItemTemplate = ContentItemTemplateSelector.SelectTemplate(selectedItem, this);
87+
}
88+
}
89+
}
90+
}

0 commit comments

Comments
 (0)