Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,19 @@ public partial class NavigationView
"HeaderContent",
typeof(object),
typeof(NavigationView),
new FrameworkPropertyMetadata(null)
new FrameworkPropertyMetadata(null, OnHeaderContentChanged)
);

private static void OnHeaderContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is not FrameworkElement frameworkElement)
{
return;
}

GetNavigationParent(frameworkElement)?.NotifyHeaderContentChanged(frameworkElement, e.NewValue);
}

/// <summary>Helper for getting <see cref="HeaderContentProperty"/> from <paramref name="target"/>.</summary>
/// <param name="target"><see cref="FrameworkElement"/> to read <see cref="HeaderContentProperty"/> from.</param>
/// <returns>HeaderContent property value.</returns>
Expand Down
13 changes: 13 additions & 0 deletions src/Wpf.Ui/Controls/NavigationView/NavigationView.Base.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ public NavigationView()

protected Dictionary<Type, INavigationViewItem> PageTypeNavigationViewsDictionary { get; } = [];

protected Dictionary<FrameworkElement, INavigationViewItem> PageToNavigationItemDictionary { get; } = [];

private readonly ObservableCollection<string> _autoSuggestBoxItems = [];
private readonly ObservableCollection<NavigationViewBreadcrumbItem> _breadcrumbBarItems = [];

Expand Down Expand Up @@ -126,6 +128,7 @@ protected virtual void OnUnloaded(object sender, RoutedEventArgs e)

PageIdOrTargetTagNavigationViewsDictionary.Clear();
PageTypeNavigationViewsDictionary.Clear();
PageToNavigationItemDictionary.Clear();

ClearJournal();

Expand Down Expand Up @@ -508,5 +511,15 @@ private void NavigationStackOnCollectionChanged(object? sender, NotifyCollection
default:
throw new ArgumentOutOfRangeException(nameof(e), e.Action, $"Unsupported action: {e.Action}");
}

UpdateBreadcrumbContents();
}

private void UpdateBreadcrumbContents()
{
foreach (var breadcrumbItem in _breadcrumbBarItems)
{
breadcrumbItem.UpdateFromSource();
}
}
}
38 changes: 31 additions & 7 deletions src/Wpf.Ui/Controls/NavigationView/NavigationView.Navigation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -215,9 +215,19 @@ private bool NavigateInternal(

OnNavigated(pageInstance);

ApplyAttachedProperties(viewItem, pageInstance);
// Set up the association before setting DataContext
if (pageInstance is FrameworkElement frameworkElement)
{
// Set NavigationParent to allow HeaderContent property changes to find this NavigationView
frameworkElement.SetValue(NavigationParentProperty, this);
}

// Set DataContext first so bindings can resolve
UpdateContent(pageInstance, dataContext);

// Apply properties after DataContext is set
ApplyAttachedProperties(viewItem, pageInstance);

AddToNavigationStack(viewItem, addToNavigationStack, isBackwardsNavigated);
AddToJournal(viewItem, isBackwardsNavigated);

Expand Down Expand Up @@ -325,14 +335,28 @@ private object GetNavigationItemInstance(INavigationViewItem viewItem)
?? throw new InvalidOperationException("Failed to create instance of the page");
}

private static void ApplyAttachedProperties(INavigationViewItem viewItem, object pageInstance)
private void ApplyAttachedProperties(INavigationViewItem viewItem, object pageInstance)
{
if (
pageInstance is FrameworkElement frameworkElement
&& GetHeaderContent(frameworkElement) is { } headerContent
)
if (pageInstance is FrameworkElement frameworkElement)
{
// Store the association between page and navigation item
PageToNavigationItemDictionary[frameworkElement] = viewItem;

// Apply HeaderContent if already available
if (GetHeaderContent(frameworkElement) is { } headerContent)
{
viewItem.Content = headerContent;
UpdateBreadcrumbContents();
}
}
}

internal void NotifyHeaderContentChanged(FrameworkElement page, object? headerContent)
{
if (PageToNavigationItemDictionary.TryGetValue(page, out INavigationViewItem? navItem))
{
viewItem.Content = headerContent;
navItem.Content = headerContent;
UpdateBreadcrumbContents();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,33 @@
// ReSharper disable once CheckNamespace
namespace Wpf.Ui.Controls;

internal class NavigationViewBreadcrumbItem
internal class NavigationViewBreadcrumbItem : DependencyObject
{
public static readonly DependencyProperty ContentProperty = DependencyProperty.Register(
nameof(Content),
typeof(object),
typeof(NavigationViewBreadcrumbItem),
new PropertyMetadata(null));

public NavigationViewBreadcrumbItem(INavigationViewItem item)
{
Content = item.Content;
PageId = item.Id;
SourceItem = item;
Content = item.Content;
}

public object Content { get; }
public object Content
{
get => GetValue(ContentProperty);
set => SetValue(ContentProperty, value);
}

public string PageId { get; }

public INavigationViewItem SourceItem { get; }

public void UpdateFromSource()
{
SetCurrentValue(ContentProperty, SourceItem.Content);
}
}