Skip to content

Commit c449871

Browse files
Merge pull request #1 from SyncfusionExamples/Sample
Added the sample for the TabView KB
2 parents ed95a8a + 966cf39 commit c449871

39 files changed

+1285
-2
lines changed

README.md

+139-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,139 @@
1-
# How-to-Customize-the-Header-of-the-Selected-Tab-in-.NET-MAUI-TabView-when-using-ItemsSource-binding
2-
This repository contains a sample explaining how to customize the Header of the Selected Tab in .NET MAUI TabView when using ItemsSource binding.
1+
This article explains how to customize the selected tab header in the [.NET MAUI TabView](https://www.syncfusion.com/maui-controls/maui-tab-view) when using the [ItemsSource](https://help.syncfusion.com/cr/maui/Syncfusion.Maui.TabView.SfTabView.html#Syncfusion_Maui_TabView_SfTabView_ItemsSource) property. The `VisualStateManager` is designed to work directly with [TabItem](https://help.syncfusion.com/cr/maui/Syncfusion.Maui.TabView.SfTabItem.html#Syncfusion_Maui_TabView_SfTabItem__ctor) but does not integrate seamlessly with the ItemsSource-based tab binding. To achieve the desired customization of the selected tab header, the [SelectionChanged](https://help.syncfusion.com/cr/maui/Syncfusion.Maui.TabView.SfTabView.html?tabs=tabid-1#Syncfusion_Maui_TabView_SfTabView_SelectionChanged) event can be leveraged, by utilizing the [EventToCommandBehavior](https://learn.microsoft.com/en-us/dotnet/communitytoolkit/maui/behaviors/event-to-command-behavior).
2+
3+
To dynamically change the text color of the selected tab header, follow these steps:
4+
5+
**Model**
6+
7+
```csharp
8+
public class Model: INotifyPropertyChanged
9+
{
10+
public event PropertyChangedEventHandler? PropertyChanged;
11+
12+
protected void OnPropertyChanged(string? propertyName)
13+
{
14+
var handler = PropertyChanged;
15+
if (handler != null)
16+
handler(this, new PropertyChangedEventArgs(propertyName));
17+
}
18+
19+
private string? name;
20+
public string? Name
21+
{
22+
get { return name; }
23+
set { name = value; OnPropertyChanged("Name"); }
24+
}
25+
26+
private Color? textColor;
27+
public Color? TextColor
28+
{
29+
get { return textColor; }
30+
set { textColor = value; OnPropertyChanged("TextColor"); }
31+
}
32+
}
33+
```
34+
35+
**ViewModel**
36+
37+
In your ViewModel, you will need to define the properties and commands to handle the selection change:
38+
39+
```csharp
40+
public class MainPageViewModel: INotifyPropertyChanged
41+
{
42+
public event PropertyChangedEventHandler PropertyChanged;
43+
44+
protected void OnPropertyChanged(string propertyName)
45+
{
46+
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
47+
}
48+
49+
private ObservableCollection<Model> tabItems;
50+
public ObservableCollection<Model> TabItems
51+
{
52+
get { return tabItems; }
53+
set { tabItems = value; OnPropertyChanged("TabItems"); }
54+
}
55+
56+
private Command<object> selectionChangedCommand;
57+
public Command<object> SelectionChangedCommand
58+
{
59+
get { return selectionChangedCommand; }
60+
set { selectionChangedCommand = value; OnPropertyChanged("SelectionChangedCommand"); }
61+
}
62+
63+
public MainPageViewModel()
64+
{
65+
TabItems = new ObservableCollection<Model>
66+
{
67+
new Model() { Name = "Alexandar", TextColor = Colors.Red },
68+
new Model() { Name = "Gabriella", TextColor = Colors.Black }
69+
// Add more items as needed
70+
};
71+
72+
SelectionChangedCommand = new Command<object>(ExecuteSelectionChangedCommand);
73+
}
74+
75+
public void ExecuteSelectionChangedCommand(object obj)
76+
{
77+
if (obj is SfTabView tabItem)
78+
{
79+
if (TabItems != null)
80+
{
81+
// Ensure the selected index is within the valid range
82+
if (tabItem.SelectedIndex >= 0 && tabItem.SelectedIndex < TabItems.Count)
83+
{
84+
for (int i = 0; i < TabItems.Count; i++)
85+
{
86+
// Set TextColor for selected tab to red, others to black
87+
TabItems[i].TextColor = (i == (int)tabItem.SelectedIndex) ? Colors.Red : Colors.Black;
88+
}
89+
}
90+
}
91+
}
92+
}
93+
}
94+
```
95+
96+
**Explanation**
97+
98+
1. **TextColor Property**: A `TextColor` property is defined within the `Model` class to allow dynamic updates to the text color of the tab headers.
99+
2. **SelectionChangedCommand**: This command is bound to the `SelectionChanged` event of the `.NET MAUI TabView`. When the selection changes, the command is executed with the `.NET MAUI TabView` instance as the command parameter.
100+
3. **ExecuteSelectionChangedCommand Method**: This method resets the text color for all tab items to the default color (black) and updates the text color of the currently selected tab to red.
101+
102+
**XAML**
103+
104+
```xml
105+
<tabView:SfTabView x:Name="tabView" ItemsSource="{Binding TabItems}" TabWidthMode="SizeToContent" TabHeaderPadding="0">
106+
<tabView:SfTabView.Behaviors>
107+
<toolkit:EventToCommandBehavior Command="{Binding SelectionChangedCommand}" CommandParameter="{x:Reference tabView}" EventName="SelectionChanged"/>
108+
</tabView:SfTabView.Behaviors>
109+
<tabView:SfTabView.HeaderItemTemplate>
110+
<DataTemplate >
111+
<Label x:Name="headerlabel" VerticalOptions="Center" Text="{Binding Name}"
112+
TextColor="{Binding TextColor}"/>
113+
</DataTemplate>
114+
</tabView:SfTabView.HeaderItemTemplate>
115+
<tabView:SfTabView.ContentItemTemplate>
116+
<DataTemplate>
117+
<Grid HorizontalOptions="Center" VerticalOptions="Center">
118+
<Label x:Name="contentLabel" Text="{Binding Name}" HorizontalOptions="Center" VerticalOptions="Center"/>
119+
</Grid>
120+
</DataTemplate>
121+
</tabView:SfTabView.ContentItemTemplate>
122+
</tabView:SfTabView>
123+
```
124+
125+
By following these steps, you can effectively customize the selected tab header in a .NET MAUI TabView when using ItemsSource binding.
126+
127+
**Output**
128+
129+
![TabViewHeaderCustomization.gif](https://support.syncfusion.com/kb/agent/attachment/article/18235/inline?token=eyJhbGciOiJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGRzaWctbW9yZSNobWFjLXNoYTI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjM0MDUxIiwib3JnaWQiOiIzIiwiaXNzIjoic3VwcG9ydC5zeW5jZnVzaW9uLmNvbSJ9.LFJsmNPHH9vWsR3CpL62ZtwF5lLr3sWpSrgckb-4pCM)
130+
131+
**Requirements to run the demo**
132+
133+
To run the demo, refer to [System Requirements for .NET MAUI](https://help.syncfusion.com/maui/system-requirements)
134+
135+
**Troubleshooting:**
136+
137+
**Path too long exception**
138+
139+
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.

TabViewSample/TabViewSample.sln

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.8.34309.116
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TabViewSample", "TabViewSample\TabViewSample.csproj", "{E377EC6C-6773-417F-9ED7-7566F6F0D6BB}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|Any CPU = Debug|Any CPU
11+
Release|Any CPU = Release|Any CPU
12+
Release-Xml|Any CPU = Release-Xml|Any CPU
13+
EndGlobalSection
14+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
15+
{E377EC6C-6773-417F-9ED7-7566F6F0D6BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
16+
{E377EC6C-6773-417F-9ED7-7566F6F0D6BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
17+
{E377EC6C-6773-417F-9ED7-7566F6F0D6BB}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
18+
{E377EC6C-6773-417F-9ED7-7566F6F0D6BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
19+
{E377EC6C-6773-417F-9ED7-7566F6F0D6BB}.Release|Any CPU.Build.0 = Release|Any CPU
20+
{E377EC6C-6773-417F-9ED7-7566F6F0D6BB}.Release|Any CPU.Deploy.0 = Release|Any CPU
21+
{E377EC6C-6773-417F-9ED7-7566F6F0D6BB}.Release-Xml|Any CPU.ActiveCfg = Release|Any CPU
22+
{E377EC6C-6773-417F-9ED7-7566F6F0D6BB}.Release-Xml|Any CPU.Build.0 = Release|Any CPU
23+
{E377EC6C-6773-417F-9ED7-7566F6F0D6BB}.Release-Xml|Any CPU.Deploy.0 = Release|Any CPU
24+
EndGlobalSection
25+
GlobalSection(SolutionProperties) = preSolution
26+
HideSolutionNode = FALSE
27+
EndGlobalSection
28+
GlobalSection(ExtensibilityGlobals) = postSolution
29+
SolutionGuid = {B69CA809-EB64-4829-B9A8-BA7F393E582F}
30+
EndGlobalSection
31+
EndGlobal

TabViewSample/TabViewSample/App.xaml

+14
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:TabViewSample"
5+
x:Class="TabViewSample.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>
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
namespace TabViewSample
2+
{
3+
public partial class App : Application
4+
{
5+
public App()
6+
{
7+
InitializeComponent();
8+
9+
MainPage = new AppShell();
10+
}
11+
}
12+
}
+15
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="TabViewSample.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:TabViewSample"
7+
Shell.FlyoutBehavior="Disabled"
8+
Title="TabViewSample">
9+
10+
<ShellContent
11+
Title="Home"
12+
ContentTemplate="{DataTemplate local:MainPage}"
13+
Route="MainPage" />
14+
15+
</Shell>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace TabViewSample
2+
{
3+
public partial class AppShell : Shell
4+
{
5+
public AppShell()
6+
{
7+
InitializeComponent();
8+
}
9+
}
10+
}
+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
3+
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
4+
x:Class="TabViewSample.MainPage"
5+
xmlns:local="clr-namespace:TabViewSample"
6+
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
7+
xmlns:tabView="clr-namespace:Syncfusion.Maui.TabView;assembly=Syncfusion.Maui.TabView">
8+
<ContentPage.BindingContext>
9+
<local:MainPageViewModel/>
10+
</ContentPage.BindingContext>
11+
<Grid>
12+
<tabView:SfTabView x:Name="tabView" ItemsSource="{Binding TabItems}" TabWidthMode="SizeToContent" TabHeaderPadding="0" FlowDirection="RightToLeft">
13+
<tabView:SfTabView.Behaviors>
14+
<toolkit:EventToCommandBehavior Command="{Binding SelectionChangedCommand}" CommandParameter="{x:Reference tabView}" EventName="SelectionChanged"/>
15+
</tabView:SfTabView.Behaviors>
16+
<tabView:SfTabView.HeaderItemTemplate>
17+
<DataTemplate >
18+
<Label x:Name="headerlabel" Padding="15,0,15,0" VerticalTextAlignment="Center" VerticalOptions="Center"
19+
Text="{Binding Name}" TextColor="{Binding TextColor}"/>
20+
</DataTemplate>
21+
</tabView:SfTabView.HeaderItemTemplate>
22+
<tabView:SfTabView.ContentItemTemplate>
23+
<DataTemplate>
24+
<Grid HorizontalOptions="Center" VerticalOptions="Center">
25+
<Label x:Name="contentLabel" TextColor="Black" Text="{Binding Name}" HorizontalOptions="Center" VerticalOptions="Center"/>
26+
</Grid>
27+
</DataTemplate>
28+
</tabView:SfTabView.ContentItemTemplate>
29+
</tabView:SfTabView>
30+
</Grid>
31+
</ContentPage>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
namespace TabViewSample
2+
{
3+
public partial class MainPage : ContentPage
4+
{
5+
public MainPage()
6+
{
7+
InitializeComponent();
8+
}
9+
}
10+
11+
}
12+
+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using Syncfusion.Maui.Core.Hosting;
2+
using Microsoft.Extensions.Logging;
3+
using CommunityToolkit.Maui;
4+
5+
namespace TabViewSample
6+
{
7+
public static class MauiProgram
8+
{
9+
public static MauiApp CreateMauiApp()
10+
{
11+
var builder = MauiApp.CreateBuilder();
12+
builder
13+
.UseMauiApp<App>()
14+
.ConfigureSyncfusionCore()
15+
.UseMauiCommunityToolkit()
16+
.ConfigureFonts(fonts =>
17+
{
18+
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
19+
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
20+
});
21+
22+
#if DEBUG
23+
builder.Logging.AddDebug();
24+
#endif
25+
26+
return builder.Build();
27+
}
28+
}
29+
}
+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System.ComponentModel;
2+
3+
namespace TabViewSample
4+
{
5+
public class Model : INotifyPropertyChanged
6+
{
7+
8+
public event PropertyChangedEventHandler? PropertyChanged;
9+
10+
protected void OnPropertyChanged(string? propertyName)
11+
{
12+
var handler = PropertyChanged;
13+
if (handler != null)
14+
handler(this, new PropertyChangedEventArgs(propertyName));
15+
}
16+
17+
private string? name;
18+
19+
public string? Name
20+
{
21+
get { return name; }
22+
set
23+
{
24+
name = value;
25+
OnPropertyChanged("Name");
26+
}
27+
}
28+
29+
private Color? textColor;
30+
public Color? TextColor
31+
{
32+
get { return textColor; }
33+
set
34+
{
35+
textColor = value;
36+
OnPropertyChanged("TextColor");
37+
}
38+
}
39+
}
40+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
3+
<application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true"></application>
4+
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
5+
<uses-permission android:name="android.permission.INTERNET" />
6+
</manifest>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using Android.App;
2+
using Android.Content.PM;
3+
using Android.OS;
4+
5+
namespace TabViewSample
6+
{
7+
[Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)]
8+
public class MainActivity : MauiAppCompatActivity
9+
{
10+
}
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using Android.App;
2+
using Android.Runtime;
3+
4+
namespace TabViewSample
5+
{
6+
[Application]
7+
public class MainApplication : MauiApplication
8+
{
9+
public MainApplication(IntPtr handle, JniHandleOwnership ownership)
10+
: base(handle, ownership)
11+
{
12+
}
13+
14+
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
15+
}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<resources>
3+
<color name="colorPrimary">#512BD4</color>
4+
<color name="colorPrimaryDark">#2B0B98</color>
5+
<color name="colorAccent">#2B0B98</color>
6+
</resources>

0 commit comments

Comments
 (0)