/* Based on Windows UI Library Copyright(c) Microsoft Corporation.All rights reserved. */ using WPFluent.Input; using System.Collections.Specialized; using System.Windows.Controls.Primitives; using System.Windows.Input; // ReSharper disable once CheckNamespace namespace WPFluent.Controls; /// /// The control provides the direct path of pages or folders to the current location. /// /// /// /// <ui:BreadcrumbBar x:Name="BreadcrumbBar" /> /// /// [StyleTypedProperty(Property = nameof(ItemContainerStyle), StyleTargetType = typeof(BreadcrumbBarItem))] public class BreadcrumbBar : System.Windows.Controls.ItemsControl { /// /// Identifies the dependency property. /// public static readonly DependencyProperty CommandProperty = DependencyProperty.Register( nameof(Command), typeof(ICommand), typeof(BreadcrumbBar), new PropertyMetadata(null)); /// /// Identifies the routed event. /// public static readonly RoutedEvent ItemClickedEvent = EventManager.RegisterRoutedEvent( nameof(ItemClicked), RoutingStrategy.Bubble, typeof(TypedEventHandler), typeof(BreadcrumbBar)); /// /// Identifies the dependency property. /// public static readonly DependencyProperty TemplateButtonCommandProperty = DependencyProperty.Register( nameof(TemplateButtonCommand), typeof(IRelayCommand), typeof(BreadcrumbBar), new PropertyMetadata(null)); /// /// Initializes a new instance of the class. /// public BreadcrumbBar() { SetValue(TemplateButtonCommandProperty, new RelayCommand(OnTemplateButtonClick)); Loaded += OnLoaded; Unloaded += OnUnloaded; } /// /// Occurs when an item is clicked in the . /// public event TypedEventHandler ItemClicked { add => AddHandler(ItemClickedEvent, value); remove => RemoveHandler(ItemClickedEvent, value); } private void InteractWithItemContainer(int offsetFromEnd, Action action) { if (ItemContainerGenerator.Items.Count <= 0) { return; } var item = ItemContainerGenerator.Items[^offsetFromEnd]; var container = (BreadcrumbBarItem)ItemContainerGenerator.ContainerFromItem(item); action.Invoke(container); } private void ItemContainerGeneratorOnItemsChanged(object sender, ItemsChangedEventArgs e) { if (e.Action != NotifyCollectionChangedAction.Remove) { return; } UpdateLastContainer(); } private void ItemContainerGeneratorOnStatusChanged(object sender, EventArgs e) { if (ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated) { return; } if (ItemContainerGenerator.Items.Count <= 1) { UpdateLastContainer(); return; } InteractWithItemContainer(2, static item => item.SetCurrentValue(BreadcrumbBarItem.IsLastProperty, false)); UpdateLastContainer(); } private void OnLoaded(object sender, RoutedEventArgs e) { ItemContainerGenerator.ItemsChanged += ItemContainerGeneratorOnItemsChanged; ItemContainerGenerator.StatusChanged += ItemContainerGeneratorOnStatusChanged; UpdateLastContainer(); } private void OnTemplateButtonClick(object obj) { if (obj is null) { throw new ArgumentNullException("Item content is null"); } var container = ItemContainerGenerator.ContainerFromItem(obj); var index = ItemContainerGenerator.IndexFromContainer(container); OnItemClicked(obj, index); } private void OnUnloaded(object sender, RoutedEventArgs e) { Loaded -= OnLoaded; Unloaded -= OnUnloaded; ItemContainerGenerator.ItemsChanged -= ItemContainerGeneratorOnItemsChanged; ItemContainerGenerator.StatusChanged -= ItemContainerGeneratorOnStatusChanged; } private void UpdateLastContainer() => InteractWithItemContainer( 1, static item => item.SetCurrentValue(BreadcrumbBarItem.IsLastProperty, true)); protected override DependencyObject GetContainerForItemOverride() { return new BreadcrumbBarItem(); } protected override bool IsItemItsOwnContainerOverride(object item) { return item is BreadcrumbBarItem; } protected virtual void OnItemClicked(object item, int index) { var args = new BreadcrumbBarItemClickedEventArgs(ItemClickedEvent, this, item, index); RaiseEvent(args); if (Command?.CanExecute(item) ?? false) { Command.Execute(item); } if (Command?.CanExecute(null) ?? false) { Command.Execute(null); } } /// /// Gets or sets custom command executed after selecting the item. /// [Bindable(true)] [Category("Action")] [Localizability(LocalizationCategory.NeverLocalize)] public ICommand Command { get => (ICommand)GetValue(CommandProperty); set => SetValue(CommandProperty, value); } /// /// Gets the triggered after clicking /// public IRelayCommand TemplateButtonCommand => (IRelayCommand)GetValue(TemplateButtonCommandProperty); }