.NET MAUI Shell - TabBar - Tab IsVisible property binding not working properly on Windows platform
- Dominant language
- C#
- Stars
- 23.3k
- Forks
- 2k
- Avg merge
- 1d 15h
- Merged PRs (30d)
- 290
Description
### Description
Setting the Shell - TabBar - Tab IsVisible property binding using MessagingCenter:
- works as expected on Android platform: the tab is removed.
- does not work in the same way on Windows platform: the tab is removed ONLY on navigating to another page.
### Steps to Reproduce
1. Create a new Project > .NET MAUI App (preview)
2. Set Project Properties Nullable = Enabled
3. Chance App.xaml.cs to the following:
namespace MauiApp1;
public partial class App : Application
{
public App()
{
InitializeComponent();
MainPage = new AppShell();
}
}
4. Chance AppShell.xaml to the following:
5. Chance AppShell.xaml.cs to the following:
namespace MauiApp1;
public partial class AppShell : Shell
{
public AppShell()
{
InitializeComponent();
BindingContext = new ViewModelAppShell();
}
}
6. Change MauiProgram.cs to the following:
namespace MauiApp1;
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp()
.ConfigureFonts(fonts =>
{
fonts.AddFont("FontAwesome5Solid.otf", "FontAwesome");
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
});
return builder.Build();
}
}
7. Add IconFont.cs as follows:
namespace MauiApp1;
static class IconFont
{
public const string Microphone = "\uf130";
public const string Backward = "\uf04a";
public const string SignOutAlt = "\uf2f5";
public const string Info = "\uf129";
public const string Home = "\uf015";
}
8. Add MessengerPage.xaml
9. Change MessengerPage.xaml.cs to the following:
namespace MauiApp1;
public partial class MessengerPage : ContentPage
{
public MessengerPage()
{
InitializeComponent();
BindingContext = new ViewModelMessengerPage();
}
}
10. Add ObservableObject.cs as follows:
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace MauiApp1;
public interface IObservableObject
{
bool SetProperty(ref T backingStore, T value, string propertyName, Action onChanged);
void OnPropertyChanged(string propertyName);
}
public class ObservableObject : INotifyPropertyChanged, IObservableObject
{
public bool SetProperty(ref T backingStore, T value,
[CallerMemberName] string propertyName = "",
Action? onChanged = null)
{
if (EqualityComparer.Default.Equals(backingStore, value)) return false;
backingStore = value;
onChanged?.Invoke();
OnPropertyChanged(propertyName);
return true;
}
public event PropertyChangedEventHandler? PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
var changed = PropertyChanged;
if (changed == null) return;
changed.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
11. Add ViewModelAppShell.cs as follows:
namespace MauiApp1;
public class ViewModelAppShell : ObservableObject
{
private bool mainPageIsVisible = true;
private bool infoPageIsVisible = true;
private bool backPageIsVisible = true;
private bool signOutPageIsVisible = true;
public bool MainPageIsVisible
{
get => mainPageIsVisible;
set => SetProperty(ref mainPageIsVisible, value);
}
public bool InfoPageIsVisible
{
get => infoPageIsVisible;
set => SetProperty(ref infoPageIsVisible, value);
}
public bool BackPageIsVisible
{
get => backPageIsVisible;
set => SetProperty(ref backPageIsVisible, value);
}
public bool SignOutPageIsVisible
{
get => signOutPageIsVisible;
set => SetProperty(ref signOutPageIsVisible, value);
}
public ViewModelAppShell()
{
MessagingCenter.Subscribe(this, "commandSendClicked", (viewModel, _Int) =>
{
switch (_Int)
{
case 1:
{
MainPageIsVisible = !mainPageIsVisible;
break;
}
case 2:
{
InfoPageIsVisible = !infoPageIsVisible;
break;
}
case 3:
{
BackPageIsVisible = !backPageIsVisible;
break;
}
case 4:
{
SignOutPageIsVisible = !signOutPageIsVisible;
break;
}
default: { break; }
}
}); ;
}
}
12. Add ViewModelMessengerPage.cs as follows:
using System.Windows.Input;
namespace MauiApp1;
public class ViewModelMessengerPage
{
public ICommand CommandSendClicked { get; }
public ViewModelMessengerPage()
{
CommandSendClicked = new Command(OnClicked);
}
private void OnClicked(object commandParameter)
{
if (int.TryParse(commandParameter.ToString(), out var _Int))
MessagingCenter.Send(this, "commandSendClicked", _Int);
}
}
### Version with bug
Release Candidate 2 (current)
### Last version that worked well
Unknown/Other
### Affected platforms
Windows
### Affected platform versions
Android 11.0 and Windows Machine
### Did you find any workaround?
No workaround
### Relevant log output
_No response_
Contributor guide
Research direction
Reproduce the behavior using the AppShell.xaml, AppShell.xaml.cs, ViewModelAppShell.cs, and ViewModelMessengerPage.cs sample from the issue. Start by comparing Shell Tab IsVisible binding updates on Android and Windows, then verify that toggling each command removes the corresponding tab immediately on Windows without navigating.】【。
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- frontend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100