A cross-platform UI framework for .NET
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

207 lines
6.8 KiB

using System.Collections.ObjectModel;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Templates;
using Avalonia.Interactivity;
using Avalonia.Layout;
using Avalonia.Media;
namespace ControlCatalog.Pages
{
public partial class TabbedPageDataTemplatePage : UserControl
{
private sealed class CategoryViewModel
{
public string Name { get; }
public string Color { get; }
public CategoryViewModel(string name, string color)
{
Name = name;
Color = color;
}
}
private static readonly CategoryViewModel[] InitialData =
{
new("Electronics", "#1565C0"), new("Books", "#2E7D32"), new("Clothing", "#6A1B9A"),
};
private static readonly CategoryViewModel[] AddData =
{
new("Sports", "#E53935"), new("Music", "#F57C00"), new("Garden", "#00796B"), new("Toys", "#E91E63"),
new("Food", "#3F51B5")
};
private readonly ObservableCollection<CategoryViewModel> _items = new();
private int _addCounter;
private bool _useDetailTemplate = true;
private TabbedPage? _tabbedPage;
public TabbedPageDataTemplatePage()
{
InitializeComponent();
Loaded += OnLoaded;
}
private void OnLoaded(object? sender, RoutedEventArgs e)
{
if (_tabbedPage != null)
return;
foreach (var vm in InitialData)
_items.Add(vm);
_addCounter = InitialData.Length;
_useDetailTemplate = true;
_tabbedPage = new TabbedPage
{
TabPlacement = TabPlacement.Top, ItemsSource = _items, PageTemplate = CreatePageTemplate()
};
_tabbedPage.SelectionChanged += OnSelectionChanged;
TabbedPageHost.Children.Add(_tabbedPage);
UpdateStatus();
}
private void OnAddCategory(object? sender, RoutedEventArgs e)
{
var idx = _addCounter % AddData.Length;
var vm = AddData[idx];
var suffix = _addCounter >= AddData.Length ? $" {_addCounter / AddData.Length + 1}" : "";
_items.Add(new CategoryViewModel(vm.Name + suffix, vm.Color));
_addCounter++;
UpdateStatus();
}
private void OnRemoveCategory(object? sender, RoutedEventArgs e)
{
if (_items.Count > 0)
{
_items.RemoveAt(_items.Count - 1);
UpdateStatus();
}
}
private void OnSelectionChanged(object? sender, PageSelectionChangedEventArgs e) => UpdateStatus();
private void OnSwitchTemplate(object? sender, RoutedEventArgs e)
{
if (_tabbedPage == null)
return;
_useDetailTemplate = !_useDetailTemplate;
_tabbedPage.PageTemplate = CreatePageTemplate();
UpdateStatus();
}
private void OnPrevious(object? sender, RoutedEventArgs e)
{
if (_tabbedPage == null)
return;
if (_tabbedPage.SelectedIndex > 0)
_tabbedPage.SelectedIndex--;
}
private void OnNext(object? sender, RoutedEventArgs e)
{
if (_tabbedPage == null)
return;
if (_tabbedPage.SelectedIndex < _items.Count - 1)
_tabbedPage.SelectedIndex++;
}
private void UpdateStatus()
{
var count = _items.Count;
var index = _tabbedPage?.SelectedIndex ?? -1;
StatusText.Text = count == 0 ? "No tabs" : $"Tab {index + 1} of {count} (index {index})";
}
private IDataTemplate CreatePageTemplate()
{
return new FuncDataTemplate<CategoryViewModel>((vm, _) => CreatePage(vm, _useDetailTemplate));
}
private static ContentPage CreatePage(CategoryViewModel? vm, bool useDetailTemplate)
{
if (vm is null)
return new ContentPage();
return new ContentPage
{
Header = vm.Name, Content = useDetailTemplate ? CreateDetailContent(vm) : CreateShowcaseContent(vm)
};
}
private static Control CreateDetailContent(CategoryViewModel vm)
{
return new StackPanel
{
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
Spacing = 8,
Children =
{
new TextBlock
{
Text = vm.Name,
FontSize = 24,
FontWeight = FontWeight.SemiBold,
Foreground = new SolidColorBrush(Color.Parse(vm.Color)),
HorizontalAlignment = HorizontalAlignment.Center
},
new TextBlock
{
Text = $"Tab for category: {vm.Name}",
FontSize = 13,
Opacity = 0.7,
TextWrapping = TextWrapping.Wrap,
TextAlignment = TextAlignment.Center,
MaxWidth = 280
}
}
};
}
private static Control CreateShowcaseContent(CategoryViewModel vm)
{
var accent = Color.Parse(vm.Color);
return new Border
{
Margin = new Thickness(24),
CornerRadius = new CornerRadius(18),
Background = new SolidColorBrush(accent),
Padding = new Thickness(28),
Child = new StackPanel
{
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
Spacing = 10,
Children =
{
new TextBlock
{
Text = vm.Name,
FontSize = 28,
FontWeight = FontWeight.Bold,
Foreground = Brushes.White,
HorizontalAlignment = HorizontalAlignment.Center
},
new TextBlock
{
Text = "Template switched at runtime",
FontSize = 14,
Foreground = Brushes.White,
Opacity = 0.9,
HorizontalAlignment = HorizontalAlignment.Center
}
}
}
};
}
}
}