I'm new to desktop development and I'm trying to implement an application where it's possible to dynamically create tabs with content based on an selected item from a list.
Items are added to the TabBar.Items collection, however I can't see them on the app window (UWP WinUI 3 Windows machine)
As you can see, the Count property on Sessions.Items points to 4, however only one tab is visually displayed [BrowserSession].
Tabs are displayed in the second application window [BrowserPage] when the list of available "tabs" is in the first window [AppShell]. Also both windows are shell based.
View
<Shell xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Browser.Views.BrowserPage"
Title="Browser"
xmlns:views="clr-namespace:Browser.Views">
<TabBar x:Name="Sessions">
</TabBar>
</Shell>
and code behind
public partial class BrowserPage : Shell
{
public BrowserPage(ObservableCollection<BrowserSessionData> sessions)
{
InitializeComponent();
BrowserSessions = sessions;
for (int i = 0; i < BrowserSessions.Count; i++)
{
var browserSession = BrowserSessions[i];
Sessions.Items.Add(new Tab
{
Title = browserSession.DisplayName,
Items = {
new ShellContent() {
Title = browserSession.DisplayName,
Route = browserSession.DisplayName,
ContentTemplate = new DataTemplate(() => new BrowserSession(browserSession))
}
}
});
}
BrowserSessions.CollectionChanged += OnCollectionChanged;
}
private ObservableCollection<BrowserSessionData> BrowserSessions { get; }
private void OnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
if(e.Action == NotifyCollectionChangedAction.Add && e.NewItems != null)
{
for (int i = 0; i < e.NewItems.Count; i++)
{
var browserSession = e.NewItems[i] as BrowserSessionData;
Sessions.Items.Add(new Tab
{
Title = browserSession.DisplayName,
Items = {
new ShellContent() {
Title = browserSession.DisplayName,
Route = browserSession.DisplayName,
ContentTemplate = new DataTemplate(() => new BrowserSession(browserSession))
}
}
});
}
}
}
}
I would be grateful for any hints
With the current release (8-8-22) there seem to be tab painting issues in Maui until navigation occurs. Calling "GoToAsync" can force this programatically.
Additionally, removing an unnecessary layer of tab objects might help the rendering situation. That is, you can simplify your structure to generate something like this:
<Shell ...>
<TabBar x:Name="Sessions">
<!-- tabs generated by the code... -->
<ShellContent Title="Tab1" Route="TabRoute" ContentTemplate="..." />
</TabBar>
</Shell>
Putting it all together: Make sure the "Route" name is unique, make your handler async
, call GoToAsync()
, and remove the extra "Tab" object:
private async void OnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
...
for (int i = 0; i < BrowserSessions.Count; i++)
{
var browserSession = BrowserSessions[i];
Sessions.Items.Add(new ShellContent()
{
Title = browserSession.DisplayName,
Route = browserSession.DisplayName,
ContentTemplate = new DataTemplate(() => new BrowserSession(browserSession))
});
}
await GoToAsync($"//{browserSession.DisplayName}");
If you want to stay on the current tab, you could navigate back after the first call to "GoToAsync" with another call to GoToAsync("..")
using the backwards navigation double-dots ".."
).