V tomto článku se podíváme, jak můžeme přizpůsobit vzhled položky nastavení v ovladacím prvku NavigationView
v UWP aplikacích.
"Zadrátované" settings
Fakt, že položka nastavení je v NavigationView
zabudována "natvrdo" jsem si poprvé uvědomil, když jsem se pokoušel zodpovědět tuto otázku od @Xinpeng na Stack Overflow a zaskočilo mě to. Tato konkrétní položka není součástí NavigationView.PaneFooter
, nýbrž je umístně ještě pod ním. A přesto, že vývojář může rozhodnout zda je zobrazena, není možné přímo manipulovat s jejími vlastnostmi. Prvním nápadem, který jsem dostal, bylo jednoduše vytvořit vlastní položku v sekci PaneFooter
. Tím však ztrácíme důležitou funkci - indikátor vybraného prvku v NavigationView
a s ním spojenou animaci. Podíval jsem se tedy místo toho do výchozí šablony NavigationView
a našel následující:
<NavigationViewItem x:Name="SettingsNavPaneItem" Grid.Row="5"> <NavigationViewItem.Icon> <SymbolIcon Symbol="Setting"/> </NavigationViewItem.Icon> </NavigationViewItem>
Položka nastavení je zde definována spolu se svou ikonou, takže její upravení je snadné. To samé se však nedá říci o textu. Ukazuje se, že ovladací prvek nastavuje vlastnost NavigationViewItem.Content
v kódu na lokalizovaný text Settings.
Vlastní NavigationView
Ideální řešení problému vyžaduje zdědit vlastní třídu od NavigationView
. Systém aplikuje výchozí šablonu v OnApplyTemplate
a v té samé chvíli nastaví Content
položky nastavení na lokalizovaný text. Zde přicházíme na řadu my. Nejprve vytvořme tříduCustomizableNavigationView
:
public class CustomizableNavigationView : NavigationView { ... }
Přidáme dvě dependency properties - jednu pro ikonu a jednu pro požadovaný text. Kód zatím nelze zkompilovat, protože používáme metodu SettingsItemChanged
kterou implementujeme později.
public static readonly DependencyProperty SettingsItemTextProperty = DependencyProperty.Register( nameof(SettingsItemText), typeof(string), typeof(CustomizableNavigationView), new PropertyMetadata(default(string), SettingsItemChanged)); public static readonly DependencyProperty SettingsItemIconProperty = DependencyProperty.Register( nameof(SettingsItemIcon), typeof(IconElement), typeof(CustomizableNavigationView), new PropertyMetadata(default(IconElement), SettingsItemChanged)); public IconElement SettingsItemIcon { get => (IconElement)GetValue(SettingsItemIconProperty); set => SetValue(SettingsItemIconProperty, value); } public string SettingsItemText { get => (string)GetValue(SettingsItemTextProperty); set => SetValue(SettingsItemTextProperty, value); }
Nyní můžeme přepsat virtuální metodu OnApplyTemplate
. Nejdříve necháme pracovat samotný ovladací prvek voláním base
implementace a pak z šablony vezmeme položku dle jména a modifikujeme ho.
private const string SettingsNavigationViewItemName = "SettingsNavPaneItem"; private NavigationViewItem _settingsItem; protected override void OnApplyTemplate() { base.OnApplyTemplate(); _settingsItem = (NavigationViewItem)GetTemplateChild(SettingsNavigationViewItemName); UpdateSettingsItemText(); }
Aktualizace položky je přímočará, pomocí aktuálních hodnot našich dependency properties.
private readonly SymbolIcon _defaultIcon = new SymbolIcon(Symbol.Setting); private void UpdateSettingsItemText() { if (_settingsItem != null) { _settingsItem.Content = SettingsItemText ?? ""; _settingsItem.Icon = SettingsItemIcon ?? _defaultIcon; } }
Nakonec pro plnohodnotnou podporu dependency properties implementujeme také property changed callback a aktualizujeme naši položku i zde.
private static void SettingsItemChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) { if (dependencyObject is CustomizableNavigationView navigationView) { navigationView.UpdateSettingsItemText(); } }
Použití výsledného ovladacího prvku je snadné. Přidáme deklaraci XML namespace do hlavičky stránky:
<Page
...
xmlns:controls="using:MyApp.Controls">
A nyní použijeme místo NavigationView
:
<controls:CustomizableNavigationView SettingsItemText="My text" IsSettingsVisible="True"> <controls:CustomizableNavigationView.SettingsItemIcon> <SymbolIcon Symbol="Edit" /> </controls:CustomizableNavigationView.SettingsItemIcon> </controls:CustomizableNavigationView>
Zdrojový kód
Zdrojový kód tohoto článku je k dispozici na mém GitHubu.
Shrnutí
I když NavigationView
obsahuje zabudovanou položku pro nastavení, není jednoduché její vzhled přizpůsobit. Stejného výsledku však naštěstí můžeme dosáhnout modifikací samotného ovladacího prvku.