AvaloniaUI / Avalonia

Develop Desktop, Embedded, Mobile and WebAssembly apps with C# and XAML. The most popular .NET UI client technology
https://avaloniaui.net
MIT License
25.95k stars 2.25k forks source link

TabControl SelectedItem not working when using ItemsSource #14371

Closed flarive closed 9 months ago

flarive commented 9 months ago

Hello,

I'm using Avalonia 11.0.7. I have created a TabControl with tab items coming from the view model.

View :

<TabControl TabStripPlacement="Top" Width="440" Height="250"
                      ItemsSource="{CompiledBinding TabItems}"
                      SelectedItem="{CompiledBinding SelectedTabItem}">

  <TabControl.Styles>
    <Style Selector="TabItem">
      <Setter Property="Height" Value="50"/>
      <Setter Property="FontSize" Value="14"/>
      <Setter Property="IsEnabled" Value="{Binding $self.((m:CustomTabItem)DataContext).Enabled}" />
      <!--<Setter Property="IsSelected" Value="{Binding $self.((m:CustomTabItem)DataContext).Selected}" />-->

      <Setter Property="HeaderTemplate">
        <DataTemplate x:DataType="m:CustomTabItem">
          <ContentPresenter Content="{CompiledBinding Header}"/>
        </DataTemplate>
      </Setter>
      <Setter Property="ContentTemplate">
        <DataTemplate x:DataType="m:CustomTabItem">
          <ContentPresenter TextWrapping="WrapWithOverflow" Content="{CompiledBinding Text}"/>
        </DataTemplate>
      </Setter>
    </Style>
  </TabControl.Styles>
</TabControl>

ViewModel :

using AvaloniaApplication1.Models;
using ReactiveUI;
using System.Collections.ObjectModel;
using System.Linq;

namespace AvaloniaApplication1.ViewModels;

public class MainViewModel : ViewModelBase
{
    #region Properties

    private ObservableCollection<CustomTabItem> _tabItems = default;
    public ObservableCollection<CustomTabItem> TabItems
    {
        get { return _tabItems; }
        set { this.RaiseAndSetIfChanged(ref _tabItems, value); }
    }

    private CustomTabItem _selectedTabItem;
    public CustomTabItem SelectedTabItem
    {
        get { return _selectedTabItem; }
        set { this.RaiseAndSetIfChanged(ref _selectedTabItem, value); }
    }

    #endregion

    public MainViewModel()
    {
        TabItems = BuildTabItems();

        SelectedTabItem = TabItems.First();
    }

    private ObservableCollection<CustomTabItem> BuildTabItems()
    {
        var menuItems = new ObservableCollection<CustomTabItem>
            {
                new CustomTabItem()
                {
                    Header = "TAB 1",
                    Text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
                },
                new CustomTabItem()
                {
                    Header = "TAB 2",
                    Text = "At erat pellentesque adipiscing commodo elit at imperdiet dui accumsan. Dolor sit amet consectetur adipiscing. Mauris vitae ultricies leo integer malesuada. Mus mauris vitae ultricies leo integer malesuada nunc. Bibendum arcu vitae elementum curabitur vitae nunc."
                },
                new CustomTabItem()
                {
                    Header = "TAB 3",
                    Text = "Risus viverra adipiscing at in tellus integer feugiat. Feugiat pretium nibh ipsum consequat nisl vel pretium lectus quam. Molestie at elementum eu facilisis. Faucibus nisl tincidunt eget nullam non nisi. Sit amet nisl suscipit adipiscing bibendum est ultricies integer quis."
                }
            };

        return menuItems;
    }
}

Model :

using AvaloniaApplication1.ViewModels;
using ReactiveUI;

namespace AvaloniaApplication1.Models
{
    public class CustomTabItem : ViewModelBase
    {
        private string _header;
        public string Header
        {
            get { return _header; }
            set { this.RaiseAndSetIfChanged(ref _header, value); }
        }

        private string _text;
        public string Text
        {
            get { return _text; }
            set { this.RaiseAndSetIfChanged(ref _text, value); }
        }

        //private bool _selected;
        //public bool Selected
        //{
        //    get { return _selected; }
        //    set { this.RaiseAndSetIfChanged(ref _selected, value); }
        //}

        private bool _enabled = true;
        public bool Enabled
        {
            get { return _enabled; }
            set { this.RaiseAndSetIfChanged(ref _enabled, value); }
        }
    }
}

Content is not changing when i click on tabs, why ? I have tried to play with TabControl SelectedIndex, SelectedItem, SelectedValue, SelectedValueBinding and also with TabItem IsSelected but nothing seems to work...

Could you help me please ?

Here is sample repro repo : https://github.com/flarive/AvaloniaTabControlSelectedItemNotWorking

Thank you so much for your help :)

Eviral

workgroupengineering commented 9 months ago
<UserControl xmlns="https://github.com/avaloniaui"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:vm="clr-namespace:AvaloniaApplication1.ViewModels"
             xmlns:m="clr-namespace:AvaloniaApplication1.Models"
             mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
             x:Class="AvaloniaApplication1.Views.MainView"
             x:CompileBindings="True"
             x:DataType="vm:MainViewModel">

    <Design.DataContext>
        <!-- This only sets the DataContext for the previewer in an IDE,
         to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) -->
        <vm:MainViewModel />
    </Design.DataContext>

    <TabControl TabStripPlacement="Top" Width="440" Height="250"
                          ItemsSource="{CompiledBinding TabItems}"
                          SelectedItem="{CompiledBinding SelectedTabItem}">
        <TabControl.ItemContainerTheme>
            <ControlTheme TargetType="TabItem" BasedOn="{StaticResource {x:Type TabItem}}"
                          x:DataType="m:CustomTabItem">
                <Setter Property="Height" Value="50"/>
                <Setter Property="FontSize" Value="14"/>
                <Setter Property="IsEnabled" Value="{CompiledBinding Enabled}" />
                <Setter Property="Header" Value="{CompiledBinding .}"/>
                <Setter Property="HeaderTemplate">
                    <DataTemplate DataType="m:CustomTabItem">
                        <TextBlock Text="{CompiledBinding Header}"
                                   TextWrapping="WrapWithOverflow"/>
                    </DataTemplate>
                </Setter>
                <Setter Property="ContentTemplate">
                    <Setter.Value>
                        <DataTemplate DataType="m:CustomTabItem">
                            <TextBlock Text="{CompiledBinding Text}"
                                       TextWrapping="WrapWithOverflow"/>
                        </DataTemplate>
                    </Setter.Value>
                </Setter>
                <Setter Property="Content" Value="{CompiledBinding}"/>
            </ControlTheme>
        </TabControl.ItemContainerTheme>
    </TabControl>
</UserControl>
timunie commented 9 months ago

@flarive can we open Q&A instead of a bug report for questions please?

flarive commented 9 months ago

Yes sure @timunie, seems that i missed something, doesn't seem to be a bug actually...

timunie commented 9 months ago

Will reopen it if it is a bug.

flarive commented 9 months ago

Thanks a lot @workgroupengineering, it works perfectly !