In WinUI3, How to make the TabItems load the corresponding page after clicking and selecting them

C CB 85 Reputation points
2024-06-27T08:36:37.03+00:00

In WinUI3, TabView has some TabItems. how to make the TabItems load the corresponding page after clicking and selecting them. My codes as following, but they don't work( Just check the second tab).

<?xml version="1.0" encoding="utf-8"?>
<Window
    x:Class="MyTest.TestWindowTabView"     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:MyTest"     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <StackPanel Orientation="Vertical">
        <Button x:Name="AddTab" Click="Add_Click">Add New Tab</Button>
        <TabView x:Name="MyTabView" SelectionChanged="TabViewItem_SelectionChanged"  >
            <TabView.TabItemTemplate>
                <DataTemplate x:DataType="local:TabItemViewModel">
                    <TabViewItem Header="{x:Bind Title}">
                        <TabViewItem.Content>
                            <ContentPresenter Content="{x:Bind Content}"/>
                        </TabViewItem.Content>
                    </TabViewItem>
                </DataTemplate>
            </TabView.TabItemTemplate>
        </TabView>
    </StackPanel>
</Window>

using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using Microsoft.UI.Xaml.Data;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Navigation;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
// To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: http://aka.ms/winui-project-info.
namespace MyTest
{
    /// <summary>
    /// An empty window that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class TestWindowTabView : Window
    {
        public ObservableCollection<TabItemViewModel> Tabs { get; } = new ObservableCollection<TabItemViewModel>();
        public TestWindowTabView()
        {
            this.InitializeComponent();
            Tabs.Add(new TabItemViewModel { Title = "Tab 1", Content = new TextBlock { Text = "Content of Tab1" } });
            // Keep the Content as null, I want the content loaded only after the TabItem selected.
            // the lazy loading will be done in the SelectionChanged event, but it doesn't work.
            Tabs.Add(new TabItemViewModel { Title = "Tab 2" }); 
            Tabs.Add(new TabItemViewModel { Title = "Tab 3", Content = new TextBlock { Text = "Content of Tab3" } });
            MyTabView.TabItemsSource = Tabs;
        }
        private void Add_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
        {
            Tabs.Add(new TabItemViewModel { Title = "Tab 3" });
        }
        private async void TabViewItem_SelectionChanged(Object sender, SelectionChangedEventArgs args)
        { 
            if (MyTabView.SelectedItem is TabItemViewModel selectedItem)
            {
                if (selectedItem.Content == null)
                {
                    await selectedItem.LoadContentAsync();
                }
            }
        }
    }
}

using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace MyTest
{
    public class TabItemViewModel : INotifyPropertyChanged
    {
        public string Title { get; set; }
        private UIElement _content;
        public UIElement Content
        {
            get => _content;
            set
            {
                _content = value;
                OnPropertyChanged(nameof(Content));
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        public async Task LoadContentAsync()
        {
            // for example only, just load a simple TextBlock
            Content = new TextBlock { Text = $"Content of {Title}" };
        }
    }
}

Windows App SDK
Windows App SDK
A set of Microsoft open-source libraries, frameworks, components, and tools to be used in apps to access Windows platform functionality on many versions of Windows. Previously known as Project Reunion.
743 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,555 questions
0 comments No comments
{count} votes

Accepted answer
  1. Jeanine Zhang-MSFT 9,431 Reputation points Microsoft Vendor
    2024-06-28T02:35:04.4433333+00:00

    Hello,

    Welcome to Microsoft Q&A!

    I suggest you could try to use Binding instead of x:Bind.

                        <TabViewItem.Content>
                            <ContentPresenter Content="{Binding Content}"/>
                        </TabViewItem.Content>
    

    Or you could try to modify the mode of the x:Bind.

                        <TabViewItem.Content>
                            <ContentPresenter Content="{x:Bind Content, , Mode=OneWay}"/>
                        </TabViewItem.Content>
    

    For more details you could refer the Doc: Windows data binding in depth

    Mode can be OneTime, OneWay, or TwoWay. {x:Bind} defaults to OneTime; {Binding} defaults to OneWay.

    Thank you.

    Jeanine


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful