0

I would like to set the background colour of my NavigationViewItem in the Selected and SelectedPointerOver states dynamically, to match the colour of a page that has been navigated to. It seems very hard to do without re-writing the control template snd also deriving from NavigationViewItem to add a new property. Is there any simpler way? Is it possible to override state transitions for example?

sjb-sjb
  • 1,112
  • 6
  • 14

3 Answers3

0

You can override the resources like this:

// Keep default resources in case you need to bring them back.
SelectedDefaultBrush = App.Current.Resources["NavigationViewItemBackgroundSelected"];
App.Current.Resources["NavigationViewItemBackgroundSelected"] = new SolidColorBrush(Colors.HotPink);
SelectedPointerOverDefaultBrush = App.Current.Resources["NavigationViewItemBackgroundSelectedPointerOver"];
App.Current.Resources["NavigationViewItemBackgroundSelectedPointerOver"] = new SolidColorBrush(Colors.SkyBlue);

Check this to locate generic.xaml which has the default styles.

Andrew KeepCoding
  • 7,040
  • 2
  • 14
  • 21
  • I tried this but the problem is you cannot update resources dynamically while the control is in use. Depending on the exact moment that you try to update the resource, it may work or it may fail. I'm guessing that is because sometimes the resource is locked / in use and can't be changed while it is in use. – sjb-sjb Mar 16 '23 at 15:45
  • If I had more clarity on when the resources can / cannot be updated, that might provide an avenue to a solution. – sjb-sjb Mar 16 '23 at 15:46
0

You can refer the NavigationViewItem document control-style-and-template.

The resources for this control are listed in the ThemeDictionaries section of the NavigationView_rs2_themeresources.xaml file on GitHub.

You can modify the background color of each NavigationViewItem in xaml.

<NavigationViewItem Tag="music" Content="Music">
    <NavigationViewItem.Resources>
        <ResourceDictionary>
            <SolidColorBrush x:Key="NavigationViewItemBackgroundSelected" Color="Green"/>
            <SolidColorBrush x:Key="NavigationViewItemBackgroundSelectedPointerOver" Color="Yellow"/>
        </ResourceDictionary>
    </NavigationViewItem.Resources>
</NavigationViewItem>

Update 3/24/2023

Dynamically modifying XAML resources is not an elegant solution, as @chingucoding said, if you know that one element color, you can set the Resources of that specific item and override the colors.

For this issue: https://github.com/microsoft/microsoft-ui-xaml/issues/8283

You need set the Resources for each NavigationViewItem.

<NavigationViewItem.Resources>
    <ResourceDictionary>
        <SolidColorBrush x:Key="NavigationViewSelectionIndicatorForeground" Color="Yellow"/>
    </ResourceDictionary>
</NavigationViewItem.Resources>
Junjie Zhu - MSFT
  • 2,086
  • 1
  • 2
  • 6
  • 1
    If you just want to use different colors for each specific page and you won't change it later, this answer from Junjie is definitely the way to go. – Andrew KeepCoding Mar 16 '23 at 02:44
  • I am aware of this but it does not allow changing the color dynamically based on another UI element i.e. based on the background color of a Page that was navigated to in a nearby Frame. – sjb-sjb Mar 16 '23 at 15:41
  • Setting resources doesn't work very well either, see https://github.com/microsoft/microsoft-ui-xaml/issues/8283 – sjb-sjb Mar 16 '23 at 15:43
  • I checked the code https://github.com/microsoft/microsoft-ui-xaml/blob/main/dev/NavigationView/NavigationView_rs1_themeresources.xaml#L743, I also can reproduce the same problem, this may be a bug. – Junjie Zhu - MSFT Mar 17 '23 at 10:16
  • @sjb-sjb , you can see my edit today. – Junjie Zhu - MSFT Mar 24 '23 at 06:52
0

If you know that one element will always need to be green while another element will always be red, you might be able to set the Resources of that specific item and override the colors as someone else already suggested. Otherwise, I think the only option would be to actually grab the UI elements and update their Background property yourself or introduce a new property for this. Note though that in either case, you will need to update the SelectionIndicator too. I'm afraid there isn't an elegant solution to this.

PS: Updating resources while they are used is not something I would encourage doing, especially since it's flaky in behavior.

chingucoding
  • 894
  • 7
  • 17