Home > Mobile >  Automatically resize tab headers based on the count of tabs (AvaloniaUI)
Automatically resize tab headers based on the count of tabs (AvaloniaUI)

Time:12-01

I want to implement styling for TabControl in my browser like in chrome. The number of tabs is not fixed, so I want the tab headers to decrease depending on the number of tabs.

To do this, I bind the width of the Grid in the DataTemplate to the count of tabs, which is passed to the converter, which returns the actual width.

But for some reason this does not work, I know that the TabItemCount is accurately passed to the converter. If the converter returns a fixed value, then nothing prevents the tabs from resizing

Style:

<Style Selector="TabControl">
        <Setter Property="BorderThickness" Value="0"></Setter>
        <Setter Property="ItemsPanel">
            <ItemsPanelTemplate>
                <StackPanel Orientation="Horizontal" 
                            Height="50"
                            Margin="10,-5,-10,5"></StackPanel>
            </ItemsPanelTemplate>
        </Setter>
        <Setter Property="ContentTemplate">
            <DataTemplate DataType="vm:WebsiteTabVM">
                <views:WebsiteTab></views:WebsiteTab>
            </DataTemplate>
        </Setter>
        <Setter Property="ItemTemplate">
            <DataTemplate DataType="vm:TabVM">
                <Grid Width="{Binding DataContext.TabItemCount, 
                             Converter={StaticResource CountToWidthConverter},
                             RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TabControl}}}"
                      HorizontalAlignment="Center" VerticalAlignment="Center"
                      Margin="5">

                      <!--ItemTemplate-->

CountToWidthConverter:

using Avalonia.Data.Converters;
using System;

namespace SimpleBrowser.Helpers
{
    public class CountToWidthConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return 1000 / (int)value;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

MainVM, which has a count of tabs property:

using Avalonia.Controls;
using Microsoft.Toolkit.Mvvm.Input;
using ReactiveUI;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows.Input;
using System.Linq;

namespace SimpleBrowser.ViewModels
{
    public class MainVM : ViewModelBase
    {
        public MainVM()
        {
            TabVMs = new ObservableCollection<TabVM>();
            TabVMs.Add(new WebsiteTabVM());
            TabVMs.Add(new WebsiteTabVM() {Name="Test tab withbigtext"});
            TabVMs.Add(new WebsiteTabVM());
            TabVMs.Add(new WebsiteTabVM());

            SortTabs();
        }
        private ObservableCollection<TabVM> _tabVMs;
        public ObservableCollection<TabVM> TabVMs
        {
            get { return _tabVMs; }
            set 
            { 
                this.RaiseAndSetIfChanged(ref _tabVMs, value);
                TabItemCount = TabVMs.Count;
            }
        }

        private double _tabItemCount;
        public double TabItemCount
        {
            get { return _tabItemCount; }
            set { this.RaiseAndSetIfChanged(ref _tabItemCount, value); }
        }

        #region Command
        private ICommand _addNewTab;
        public ICommand AddNewTab
        {
            get
            {
                return _addNewTab ??= new RelayCommand(() =>
                {
                    TabVMs.Add(new WebsiteTabVM());
                    SortTabs();
                });
            }
        }
        private ICommand _removeTab;
        public ICommand RemoveTab
        {
            get
            {
                return _removeTab ??= new RelayCommand<int>(obj =>
                {
                    TabVMs.RemoveAt(obj);
                    SortTabs();
                });
            }
        }
        #endregion

        public void SortTabs()
        {
            for (int i = 0; i < TabVMs.Count; i  )
            {
                TabVMs[i].Index = i;
                TabVMs[i].IsTabLast = false;
            }
            TabVMs.Last().IsTabLast = true;
            TabItemCount = TabVMs.Count;
        }
    }
}

If you need more code, I will definitely provide you with it. Thanks for considering my request

CodePudding user response:

I think you could just use UniformGrid as a panel template, so you get all those calculations for free

<TabControl.ItemsPanel>
    <ItemsPanelTemplate>
        <UniformGrid Rows="1" HorizontalAlignment="Left"/>
    </ItemsPanelTemplate>
</TabControl.ItemsPanel>

Then you might want to specify the MinWidth and MaxWidth of the TabItem and manage the maximum number of tabs in the view model.

  • Related