Open misakieku opened 8 months ago
In Wpf.Ui.Controls.NavigationView source code, there is an update menu items template function. You can manually update it by doing the same for loop after adding your items in your code. just copy the for loop and adjust according to your variables. This is how i solved it at least.
protected virtual void UpdateMenuItemsTemplate(IList list) { for (int i = 0; i < list.Count; i++) { if (list[i] is NavigationViewItem navigationViewItem && ItemTemplate != null && navigationViewItem.Template != ItemTemplate) { navigationViewItem.Template = ItemTemplate; } } }
In Wpf.Ui.Controls.NavigationView source code, there is an update menu items template function. You can manually update it by doing the same for loop after adding your items in your code. just copy the for loop and adjust according to your variables. This is how i solved it at least.
protected virtual void UpdateMenuItemsTemplate(IList list) { for (int i = 0; i < list.Count; i++) { if (list[i] is NavigationViewItem navigationViewItem && ItemTemplate != null && navigationViewItem.Template != ItemTemplate) { navigationViewItem.Template = ItemTemplate; } } }
It did work. However, OnNavigationSelectionChanged will not be trigger if I select the new item that I added.
And this seams not working if I add the item as a subitem of another navigation view item.
You are right. I made a workaround by recreating the navigation view at every update and then re initialize it in the xaml. I also add the selection changed events which triggers it successfully. This works for me but it is not a good way of updating it at all.
` var newNavigationView = new NavigationView { MenuItemsSource = MenuItems, Header = NavigationView.Header, IsPaneOpen = NavigationView.IsPaneOpen, PaneDisplayMode = NavigationView.PaneDisplayMode, };
newNavigationView.SelectionChanged += NavigationView_SelectionChanged; var parent = NavigationView.Parent as Panel; if (parent != null) { int index = parent.Children.IndexOf(NavigationView); parent.Children.RemoveAt(index); parent.Children.Insert(index, newNavigationView); }
NavigationService.SetNavigationControl(newNavigationView);
NavigationView = newNavigationView;`
You are right. I made a workaround by recreating the navigation view at every update and then re initialize it in the xaml. I also add the selection changed events which triggers it successfully. This works for me but it is not a good way of updating it at all.
` var newNavigationView = new NavigationView { MenuItemsSource = MenuItems, Header = NavigationView.Header, IsPaneOpen = NavigationView.IsPaneOpen, PaneDisplayMode = NavigationView.PaneDisplayMode, };
newNavigationView.SelectionChanged += NavigationView_SelectionChanged; var parent = NavigationView.Parent as Panel; if (parent != null) { int index = parent.Children.IndexOf(NavigationView); parent.Children.RemoveAt(index); parent.Children.Insert(index, newNavigationView); }
NavigationService.SetNavigationControl(newNavigationView);
NavigationView = newNavigationView;`
Thanks a lot.
after some research I found the following solution
I change the Visible
value instead of adding and removing the menu item
<ui:NavigationView x:Name="NavigationView" Grid.Row="1" Padding="10,0,10,0"
BreadcrumbBar="{Binding ElementName=BreadcrumbBar}"
FooterMenuItemsSource="{Binding ViewModel.FooterMenuItems, Mode=OneWay}" FrameMargin="0"
IsBackButtonVisible="Visible" IsPaneToggleVisible="True" PaneDisplayMode="LeftFluent">
<ui:NavigationView.Header>
<ui:BreadcrumbBar x:Name="BreadcrumbBar" Margin="10,5,10,5" />
</ui:NavigationView.Header>
<ui:NavigationView.ContentOverlay>
<Grid>
<ui:SnackbarPresenter x:Name="SnackbarPresenter" />
</Grid>
</ui:NavigationView.ContentOverlay>
<ui:NavigationView.MenuItems>
<ui:NavigationViewItem Content="Devices" TargetPageType="{x:Type pages:DevicesPage}">
<ui:NavigationViewItem.Icon>
<ui:SymbolIcon Symbol="DeviceEq20" />
</ui:NavigationViewItem.Icon>
</ui:NavigationViewItem>
<ui:NavigationViewItem Content="Users" TargetPageType="{x:Type pages:UsersPage}">
<ui:NavigationViewItem.Icon>
<ui:SymbolIcon Symbol="People20" />
</ui:NavigationViewItem.Icon>
</ui:NavigationViewItem>
<ui:NavigationViewItem Content="Account" TargetPageType="{x:Type pages:AccountPage}">
<ui:NavigationViewItem.Icon>
<ui:SymbolIcon Symbol="NotepadPerson20" />
</ui:NavigationViewItem.Icon>
</ui:NavigationViewItem>
<!--look here trick is here-->
<ui:NavigationViewItem Content="Connected" TargetPageType="{x:Type pages:SettingsPage}"
Visibility="{Binding ViewModel.ShowConnectedTab, Converter={StaticResource BoolToVisibleConvertor}}"
>
<ui:NavigationViewItem.Icon>
<ui:SymbolIcon Symbol="NotepadPerson20" />
</ui:NavigationViewItem.Icon>
</ui:NavigationViewItem>
</ui:NavigationView.MenuItems>
</ui:NavigationView>
And my view model
public partial class MainWindowViewModel : ObservableObject {
[ObservableProperty]
private string _applicationTitle = "Modibus Client";
[ObservableProperty]
private bool _showConnectedTab = false;
[ObservableProperty]
private ObservableCollection<object> _footerMenuItems = new()
{
new NavigationViewItem()
{
Content = "Settings",
Icon = new SymbolIcon { Symbol = SymbolRegular.Settings20 },
TargetPageType = typeof(Views.Pages.SettingsPage)
},
new NavigationViewItem()
{
Content = "Logout",
Icon = new SymbolIcon { Symbol = SymbolRegular.ArrowExit20 },
TargetPageType = typeof(Views.Pages.SettingsPage)
},
};
[ObservableProperty]
public string _deviceName = "device name";
[ObservableProperty]
public string _location = "location";
// LOOK
[RelayCommand]
public void OnShowConnectedTab() {
ShowConnectedTab = true;
}
[RelayCommand]
public void OnHideConnectedTab() {
ShowConnectedTab = false;
}
}
and my converter class
internal class BoolToVisibleConvertor : IValueConverter {
public object Convert(object value,Type targetType,object parameter,CultureInfo culture) {
return (bool)value ? Visibility.Visible : Visibility.Hidden;
}
public object ConvertBack(object value,Type targetType,object parameter,CultureInfo culture) {
throw new NotImplementedException();
}
}
hi, Wpf.Ui.Controls.NavigationView source code NavigationView.Navigation.cs line: 175 - 213 - 219
if (SelectedItem != NavigationStack[0] && NavigationStack[0].IsMenuElement)
{
SelectedItem = NavigationStack[0];
OnSelectionChanged();
}
if your item is NavigationViewItem , try :
var item = AppDataUtilities.AddAppItem(appData);
item.Template = navigationView.ItemTemplate;
item.IsMenuElement = true;
navigationView.MenuItems.Add(item);
good luck!
I also have the same problem, but I hope to change the item by changing the item of ObservableCollection
public partial class MainWindow : IWindow
{
public MainWindowViewModel ViewModel
{
get;
}
public MainWindow(MainWindowViewModel viewModel, IServiceProvider serviceProvider, INavigationService navigationService)
{
ViewModel = viewModel;
// ViewModel.MenuItems = ViewModel.GetMenuItemsByAuth();//with navigation
this.DataContext = this;
viewModel.ApplicationTitle = "111111111";
InitializeComponent();
this.Loaded += MainWindow_Loaded;
navigationService.SetNavigationControl(NavigationView);
NavigationView.SetServiceProvider(serviceProvider);
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
//ViewModel.MenuItems= ViewModel.GetMenuItemsByAuth();//no Navigation
// NavigationView.MenuItems = ViewModel.GetMenuItemsByAuth();// no Navigation
// ViewModel.MenuItems.Add(new NavigationViewItem("11", SymbolRegular.Grid20, typeof(TestPage)));// no Navigation
NavigationView.MenuItems.Add(new NavigationViewItem("11", SymbolRegular.Grid20, typeof(TestPage)));// no Navigation
}
hi, Wpf.Ui.Controls.NavigationView source code NavigationView.Navigation.cs line: 175 - 213 - 219
if (SelectedItem != NavigationStack[0] && NavigationStack[0].IsMenuElement) { SelectedItem = NavigationStack[0]; OnSelectionChanged(); }
if your item is NavigationViewItem , try : var item = AppDataUtilities.AddAppItem(appData); item.Template = navigationView.ItemTemplate; item.IsMenuElement = true; navigationView.MenuItems.Add(item);
good luck!
Thanks, I also encountered this problem. Thank you for your answer
我也有同样的问题,但我希望通过更改ObservableCollection的项目来更改项目
public partial class MainWindow : IWindow { public MainWindowViewModel ViewModel { get; } public MainWindow(MainWindowViewModel viewModel, IServiceProvider serviceProvider, INavigationService navigationService) { ViewModel = viewModel; // ViewModel.MenuItems = ViewModel.GetMenuItemsByAuth();//with navigation this.DataContext = this; viewModel.ApplicationTitle = "111111111"; InitializeComponent(); this.Loaded += MainWindow_Loaded; navigationService.SetNavigationControl(NavigationView); NavigationView.SetServiceProvider(serviceProvider); } private void MainWindow_Loaded(object sender, RoutedEventArgs e) { //ViewModel.MenuItems= ViewModel.GetMenuItemsByAuth();//no Navigation // NavigationView.MenuItems = ViewModel.GetMenuItemsByAuth();// no Navigation // ViewModel.MenuItems.Add(new NavigationViewItem("11", SymbolRegular.Grid20, typeof(TestPage)));// no Navigation NavigationView.MenuItems.Add(new NavigationViewItem("11", SymbolRegular.Grid20, typeof(TestPage)));// no Navigation }
You can obtain the itemTemplate in navigationService
navigationViewItem.Template = navigationService.GetNavigationControl().ItemTemplate;
You can try it
But the indentation of the submenu is incorrect
But the indentation of the submenu is incorrect
base on: https://github.com/lepoco/wpfui/pull/964/files
You can refer to the above content about ObservableCollection.
Describe the bug
I am trying to add new Items based on configuration after the user open the app but the issue is I cannot see that the item is been added to the navigation view. The code I have now:
To Reproduce
Add NavigationViewItem during runtime, like event.
Expected behavior
NavigationView able to react the changes.
Screenshots
No response
OS version
Windows 11 VS 2022
.NET version
.Net 8
WPF-UI NuGet version
3.0.0 preview4
Additional context
No response