using WPFluent.Animations;
using System.Collections;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Windows.Controls;
// ReSharper disable once CheckNamespace
namespace WPFluent.Controls;
///
/// Defines the dependency properties and dp callbacks for control
///
public partial class NavigationView
{
private static readonly DependencyPropertyKey FooterMenuItemsPropertyKey =
DependencyProperty.RegisterReadOnly(
nameof(FooterMenuItems),
typeof(ObservableCollection),
typeof(NavigationView),
new PropertyMetadata(null));
private static readonly DependencyPropertyKey MenuItemsPropertyKey = DependencyProperty.RegisterReadOnly(
nameof(MenuItems),
typeof(ObservableCollection),
typeof(NavigationView),
new PropertyMetadata(null));
///
/// Identifies the dependency property.
///
public static readonly DependencyProperty AlwaysShowHeaderProperty = DependencyProperty.Register(
nameof(AlwaysShowHeader),
typeof(bool),
typeof(NavigationView),
new FrameworkPropertyMetadata(false));
///
/// Identifies the dependency property.
///
public static readonly DependencyProperty AutoSuggestBoxProperty = DependencyProperty.Register(
nameof(AutoSuggestBox),
typeof(AutoSuggestBox),
typeof(NavigationView),
new FrameworkPropertyMetadata(null, OnAutoSuggestBoxChanged));
///
/// Identifies the dependency property.
///
public static readonly DependencyProperty BreadcrumbBarProperty = DependencyProperty.Register(
nameof(BreadcrumbBar),
typeof(Controls.BreadcrumbBar),
typeof(NavigationView),
new FrameworkPropertyMetadata(null, OnBreadcrumbBarChanged));
///
/// Identifies the dependency property.
///
public static readonly DependencyProperty CompactPaneLengthProperty = DependencyProperty.Register(
nameof(CompactPaneLength),
typeof(double),
typeof(NavigationView),
new FrameworkPropertyMetadata(0D));
///
/// Identifies the dependency property.
///
public static readonly DependencyProperty ContentOverlayProperty = DependencyProperty.Register(
nameof(ContentOverlay),
typeof(object),
typeof(NavigationView),
new FrameworkPropertyMetadata(null));
///
/// Identifies the dependency property.
///
public static readonly DependencyProperty EnableDebugMessagesProperty = DependencyProperty.Register(
nameof(EnableDebugMessages),
typeof(bool),
typeof(NavigationView),
new FrameworkPropertyMetadata(false));
///
/// Identifies the dependency property.
///
public static readonly DependencyProperty FooterMenuItemsProperty =
FooterMenuItemsPropertyKey.DependencyProperty;
///
/// Identifies the dependency property.
///
public static readonly DependencyProperty FooterMenuItemsSourceProperty = DependencyProperty.Register(
nameof(FooterMenuItemsSource),
typeof(object),
typeof(NavigationView),
new FrameworkPropertyMetadata(null, OnFooterMenuItemsSourceChanged));
///
/// Identifies the dependency property.
///
public static readonly DependencyProperty FrameMarginProperty = DependencyProperty.Register(
nameof(FrameMargin),
typeof(Thickness),
typeof(NavigationView),
new FrameworkPropertyMetadata(default(Thickness)));
///
/// Identifies the dependency property.
///
public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register(
nameof(Header),
typeof(object),
typeof(NavigationView),
new FrameworkPropertyMetadata(null));
///
/// Identifies the dependency property.
///
public static readonly DependencyProperty HeaderVisibilityProperty = DependencyProperty.Register(
nameof(HeaderVisibility),
typeof(Visibility),
typeof(NavigationView),
new FrameworkPropertyMetadata(Visibility.Visible));
///
/// Identifies the dependency property.
///
public static readonly DependencyProperty IsBackButtonVisibleProperty = DependencyProperty.Register(
nameof(IsBackButtonVisible),
typeof(NavigationViewBackButtonVisible),
typeof(NavigationView),
new FrameworkPropertyMetadata(NavigationViewBackButtonVisible.Auto));
///
/// Identifies the dependency property.
///
public static readonly DependencyProperty IsBackEnabledProperty = DependencyProperty.Register(
nameof(IsBackEnabled),
typeof(bool),
typeof(NavigationView),
new FrameworkPropertyMetadata(false));
///
/// Identifies the dependency property.
///
public static readonly DependencyProperty IsPaneOpenProperty = DependencyProperty.Register(
nameof(IsPaneOpen),
typeof(bool),
typeof(NavigationView),
new FrameworkPropertyMetadata(true, OnIsPaneOpenChanged));
///
/// Identifies the dependency property.
///
public static readonly DependencyProperty IsPaneToggleVisibleProperty = DependencyProperty.Register(
nameof(IsPaneToggleVisible),
typeof(bool),
typeof(NavigationView),
new FrameworkPropertyMetadata(true));
///
/// Identifies the dependency property.
///
public static readonly DependencyProperty IsPaneVisibleProperty = DependencyProperty.Register(
nameof(IsPaneVisible),
typeof(bool),
typeof(NavigationView),
new FrameworkPropertyMetadata(false));
///
/// Identifies the dependency property.
///
public static readonly DependencyProperty ItemTemplateProperty = DependencyProperty.Register(
nameof(ItemTemplate),
typeof(ControlTemplate),
typeof(NavigationView),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsMeasure, OnItemTemplateChanged));
///
/// Identifies the dependency property.
///
public static readonly DependencyProperty MenuItemsProperty = MenuItemsPropertyKey.DependencyProperty;
///
/// Identifies the dependency property.
///
public static readonly DependencyProperty MenuItemsSourceProperty = DependencyProperty.Register(
nameof(MenuItemsSource),
typeof(object),
typeof(NavigationView),
new FrameworkPropertyMetadata(null, OnMenuItemsSourceChanged));
///
/// Identifies the dependency property.
///
public static readonly DependencyProperty OpenPaneLengthProperty = DependencyProperty.Register(
nameof(OpenPaneLength),
typeof(double),
typeof(NavigationView),
new FrameworkPropertyMetadata(0D));
///
/// Identifies the dependency property.
///
public static readonly DependencyProperty PaneDisplayModeProperty = DependencyProperty.Register(
nameof(PaneDisplayMode),
typeof(NavigationViewPaneDisplayMode),
typeof(NavigationView),
new FrameworkPropertyMetadata(NavigationViewPaneDisplayMode.Left, OnPaneDisplayModeChanged));
///
/// Identifies the dependency property.
///
public static readonly DependencyProperty PaneFooterProperty = DependencyProperty.Register(
nameof(PaneFooter),
typeof(object),
typeof(NavigationView),
new FrameworkPropertyMetadata(null));
///
/// Identifies the dependency property.
///
public static readonly DependencyProperty PaneHeaderProperty = DependencyProperty.Register(
nameof(PaneHeader),
typeof(object),
typeof(NavigationView),
new FrameworkPropertyMetadata(null));
///
/// Identifies the dependency property.
///
public static readonly DependencyProperty PaneTitleProperty = DependencyProperty.Register(
nameof(PaneTitle),
typeof(string),
typeof(NavigationView),
new FrameworkPropertyMetadata(null));
///
/// Identifies the dependency property.
///
public static readonly DependencyProperty TitleBarProperty = DependencyProperty.Register(
nameof(TitleBar),
typeof(TitleBar),
typeof(NavigationView),
new FrameworkPropertyMetadata(null, OnTitleBarChanged));
///
/// Identifies the dependency property.
///
public static readonly DependencyProperty TransitionDurationProperty = DependencyProperty.Register(
nameof(TransitionDuration),
typeof(int),
typeof(NavigationView),
new FrameworkPropertyMetadata(200));
///
/// Identifies the dependency property.
///
public static readonly DependencyProperty TransitionProperty = DependencyProperty.Register(
nameof(Transition),
typeof(Transition),
typeof(NavigationView),
new FrameworkPropertyMetadata(Transition.FadeInWithSlide));
private static void OnAutoSuggestBoxChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if(d is not NavigationView navigationView)
{
return;
}
if(e.NewValue is null && e.OldValue is AutoSuggestBox oldValue)
{
oldValue.SuggestionChosen -= navigationView.AutoSuggestBoxOnSuggestionChosen;
oldValue.QuerySubmitted -= navigationView.AutoSuggestBoxOnQuerySubmitted;
return;
}
if(e.NewValue is not AutoSuggestBox autoSuggestBox)
{
return;
}
autoSuggestBox.OriginalItemsSource = navigationView._autoSuggestBoxItems;
autoSuggestBox.SuggestionChosen += navigationView.AutoSuggestBoxOnSuggestionChosen;
autoSuggestBox.QuerySubmitted += navigationView.AutoSuggestBoxOnQuerySubmitted;
if(navigationView.TitleBar?.Margin == TitleBarPaneOpenMarginDefault &&
autoSuggestBox.Margin is { Bottom: 0, Left: 0, Right: 0, Top: 0 })
{
autoSuggestBox.Margin = AutoSuggestBoxMarginDefault;
}
}
private static void OnBreadcrumbBarChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if(d is not NavigationView navigationView)
{
return;
}
if(e.NewValue is null && e.OldValue is Controls.BreadcrumbBar oldValue)
{
oldValue.ItemClicked -= navigationView.BreadcrumbBarOnItemClicked;
{
return;
}
}
if(e.NewValue is not Controls.BreadcrumbBar breadcrumbBar)
{
return;
}
breadcrumbBar.ItemsSource = navigationView._breadcrumbBarItems;
breadcrumbBar.ItemTemplate ??=
UiApplication.Current.TryFindResource("NavigationViewItemDataTemplate") as DataTemplate;
breadcrumbBar.ItemClicked += navigationView.BreadcrumbBarOnItemClicked;
}
private void OnFooterMenuItems_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
if(e.NewItems is null)
{
return;
}
UpdateMenuItemsTemplate(e.NewItems);
AddItemsToDictionaries(e.NewItems);
}
private static void OnFooterMenuItemsSourceChanged(DependencyObject? d, DependencyPropertyChangedEventArgs e)
{
if(d is not NavigationView navigationView)
{
return;
}
navigationView.FooterMenuItems.Clear();
if(e.NewValue is IEnumerable newItemsSource and not string)
{
foreach(var item in newItemsSource)
{
navigationView.FooterMenuItems.Add(item);
}
}
else if(e.NewValue != null)
{
navigationView.FooterMenuItems.Add(e.NewValue);
}
if(e.NewValue is INotifyCollectionChanged oc)
{
oc.CollectionChanged += (s, e) => navigationView.OnMenuItemsSource_CollectionChanged(
oc,
navigationView.FooterMenuItems,
e);
}
}
private static void OnIsPaneOpenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if(d is not NavigationView navigationView)
{
return;
}
if((bool)e.NewValue == (bool)e.OldValue)
{
return;
}
if(navigationView.IsPaneOpen)
{
navigationView.OnPaneOpened();
}
else
{
navigationView.OnPaneClosed();
}
navigationView.CloseNavigationViewItemMenus();
navigationView.TitleBar?.SetCurrentValue(
MarginProperty,
navigationView.IsPaneOpen ? TitleBarPaneOpenMarginDefault : TitleBarPaneCompactMarginDefault);
UpdateVisualState(navigationView);
}
private static void OnItemTemplateChanged(DependencyObject? d, DependencyPropertyChangedEventArgs e)
{
if(d is not NavigationView navigationView)
{
return;
}
navigationView.OnItemTemplateChanged();
}
private void OnMenuItems_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
if(e.NewItems is null)
{
return;
}
UpdateMenuItemsTemplate(e.NewItems);
AddItemsToDictionaries(e.NewItems);
}
private void OnMenuItemsSource_CollectionChanged(
object? sender,
IList collection,
NotifyCollectionChangedEventArgs e)
{
if(ReferenceEquals(sender, collection))
{
return;
}
switch(e.Action)
{
case NotifyCollectionChangedAction.Add:
if(e.NewItems is not null)
{
foreach(var item in e.NewItems)
{
collection.Add(item);
}
}
break;
case NotifyCollectionChangedAction.Remove:
if(e.OldItems is not null && e.NewItems is not null)
{
foreach(var item in e.OldItems)
{
if(!e.NewItems.Contains(item))
{
collection.Remove(item);
}
}
}
break;
case NotifyCollectionChangedAction.Move:
var moveItem = MenuItems[e.OldStartingIndex];
collection.RemoveAt(e.OldStartingIndex);
collection.Insert(e.NewStartingIndex, moveItem);
break;
case NotifyCollectionChangedAction.Replace:
collection.RemoveAt(e.OldStartingIndex);
if(e.NewItems is not null)
{
collection.Insert(e.OldStartingIndex, e.NewItems[0]);
}
break;
case NotifyCollectionChangedAction.Reset:
collection.Clear();
break;
}
}
private static void OnMenuItemsSourceChanged(DependencyObject? d, DependencyPropertyChangedEventArgs e)
{
if(d is not NavigationView navigationView)
{
return;
}
navigationView.MenuItems.Clear();
if(e.NewValue is IEnumerable newItemsSource and not string)
{
foreach(var item in newItemsSource)
{
navigationView.MenuItems.Add(item);
}
}
else if(e.NewValue != null)
{
navigationView.MenuItems.Add(e.NewValue);
}
if(e.NewValue is INotifyCollectionChanged oc)
{
oc.CollectionChanged += (s, e) => navigationView.OnMenuItemsSource_CollectionChanged(
oc,
navigationView.MenuItems,
e);
}
}
private static void OnPaneDisplayModeChanged(DependencyObject? d, DependencyPropertyChangedEventArgs e)
{
if(d is not NavigationView navigationView)
{
return;
}
navigationView.OnPaneDisplayModeChanged();
}
private static void OnTitleBarChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if(d is not NavigationView navigationView)
{
return;
}
if(e.NewValue is null && e.OldValue is TitleBar oldValue)
{
navigationView.FrameMargin = new Thickness(0);
oldValue.Margin = new Thickness(0);
if(navigationView.AutoSuggestBox?.Margin == AutoSuggestBoxMarginDefault)
{
navigationView.AutoSuggestBox.SetCurrentValue(MarginProperty, new Thickness(0));
}
return;
}
if(e.NewValue is not TitleBar titleBar)
{
return;
}
navigationView.FrameMargin = FrameMarginDefault;
titleBar.Margin = TitleBarPaneOpenMarginDefault;
if(navigationView.AutoSuggestBox?.Margin is { Bottom: 0, Left: 0, Right: 0, Top: 0 })
{
navigationView.AutoSuggestBox.SetCurrentValue(MarginProperty, AutoSuggestBoxMarginDefault);
}
}
///
public bool AlwaysShowHeader
{
get => (bool)GetValue(AlwaysShowHeaderProperty);
set => SetValue(AlwaysShowHeaderProperty, value);
}
///
public AutoSuggestBox? AutoSuggestBox
{
get => (AutoSuggestBox?)GetValue(AutoSuggestBoxProperty);
set => SetValue(AutoSuggestBoxProperty, value);
}
///
public Controls.BreadcrumbBar? BreadcrumbBar
{
get => (Controls.BreadcrumbBar?)GetValue(BreadcrumbBarProperty);
set => SetValue(BreadcrumbBarProperty, value);
}
///
public double CompactPaneLength
{
get => (double)GetValue(CompactPaneLengthProperty);
set => SetValue(CompactPaneLengthProperty, value);
}
///
public object? ContentOverlay
{
get => GetValue(ContentOverlayProperty);
set => SetValue(ContentOverlayProperty, value);
}
///
/// Gets or sets a value indicating whether debugging messages for this control are enabled
///
public bool EnableDebugMessages
{
get => (bool)GetValue(EnableDebugMessagesProperty);
set => SetValue(EnableDebugMessagesProperty, value);
}
///
public IList FooterMenuItems => (ObservableCollection)GetValue(FooterMenuItemsProperty);
///
[Bindable(true)]
public object? FooterMenuItemsSource
{
get => GetValue(FooterMenuItemsSourceProperty);
set
{
if(value is null)
{
ClearValue(FooterMenuItemsSourceProperty);
}
else
{
SetValue(FooterMenuItemsSourceProperty, value);
}
}
}
///
public Thickness FrameMargin
{
get => (Thickness)GetValue(FrameMarginProperty);
set => SetValue(FrameMarginProperty, value);
}
///
public object? Header { get => GetValue(HeaderProperty); set => SetValue(HeaderProperty, value); }
///
public Visibility HeaderVisibility
{
get => (Visibility)GetValue(HeaderVisibilityProperty);
set => SetValue(HeaderVisibilityProperty, value);
}
///
public NavigationViewBackButtonVisible IsBackButtonVisible
{
get => (NavigationViewBackButtonVisible)GetValue(IsBackButtonVisibleProperty);
set => SetValue(IsBackButtonVisibleProperty, value);
}
///
public bool IsBackEnabled
{
get => (bool)GetValue(IsBackEnabledProperty);
protected set => SetValue(IsBackEnabledProperty, value);
}
///
public bool IsPaneOpen { get => (bool)GetValue(IsPaneOpenProperty); set => SetValue(IsPaneOpenProperty, value); }
///
public bool IsPaneToggleVisible
{
get => (bool)GetValue(IsPaneToggleVisibleProperty);
set => SetValue(IsPaneToggleVisibleProperty, value);
}
///
public bool IsPaneVisible
{
get => (bool)GetValue(IsPaneVisibleProperty);
set => SetValue(IsPaneVisibleProperty, value);
}
///
public ControlTemplate? ItemTemplate
{
get => (ControlTemplate?)GetValue(ItemTemplateProperty);
set => SetValue(ItemTemplateProperty, value);
}
///
public IList MenuItems => (ObservableCollection)GetValue(MenuItemsProperty);
///
[Bindable(true)]
public object? MenuItemsSource
{
get => GetValue(MenuItemsSourceProperty);
set
{
if(value is null)
{
ClearValue(MenuItemsSourceProperty);
}
else
{
SetValue(MenuItemsSourceProperty, value);
}
}
}
///
public double OpenPaneLength
{
get => (double)GetValue(OpenPaneLengthProperty);
set => SetValue(OpenPaneLengthProperty, value);
}
///
public NavigationViewPaneDisplayMode PaneDisplayMode
{
get => (NavigationViewPaneDisplayMode)GetValue(PaneDisplayModeProperty);
set => SetValue(PaneDisplayModeProperty, value);
}
///
public object? PaneFooter { get => GetValue(PaneFooterProperty); set => SetValue(PaneFooterProperty, value); }
///
public object? PaneHeader { get => GetValue(PaneHeaderProperty); set => SetValue(PaneHeaderProperty, value); }
///
public string? PaneTitle { get => (string?)GetValue(PaneTitleProperty); set => SetValue(PaneTitleProperty, value); }
///
public TitleBar? TitleBar
{
get => (TitleBar?)GetValue(TitleBarProperty);
set => SetValue(TitleBarProperty, value);
}
///
public Transition Transition
{
get => (Transition)GetValue(TransitionProperty);
set => SetValue(TransitionProperty, value);
}
///
[Bindable(true)]
[Category("Appearance")]
public int TransitionDuration
{
get => (int)GetValue(TransitionDurationProperty);
set => SetValue(TransitionDurationProperty, value);
}
}