Reputation: 368
I am writing this app where I use the NavigationView
control, and I would like to not have static menu items in it, so I bind this control's MenuItemsSource
property to list of menu item objects described with class like this:
public sealed class MenuItem
{
public string Name { get; set; }
// ...
}
I then template this data using DataTemplate
:
<DataTemplate x:DataType="menu:MenuItem">
<NavigationViewItem Content="{x:Bind Name}" />
</DataTemplate>
Finally, I would like to react to ItemInvoked
events, e.g. for navigation. For that I need to get the MenuItem
instance that was bound to this specific NavigationViewItem
. Alas, in event args there is only the container control itself, not the data it was made from. The closest I was to reaching the desired functionality is when binding the DataContext
property of NavigationViewItem
to bound data, like this:
<DataTemplate x:DataType="menu:MenuItem">
<NavigationViewItem Content="{x:Bind Name}" DataContext={x:Bind} />
</DataTemplate>
But it seems slightly wrong, although I cannot think of better solution. Could someone help me out?
Update: I found the method XamlBindingHelper.GetDataTemplateComponent
which returns some dynamic object with properties, and one of them is exactly the data I am after. If it is present there, why aren't there any helper methods to reliably get it back?
Upvotes: 1
Views: 314
Reputation: 169420
Your MenuItemTemplate
should not contain a NavigationViewItem
container. Replace it with a TextBlock
:
<NavigationView.MenuItemTemplate>
<DataTemplate x:DataType="menu:MenuItem">
<TextBlock Text="{x:Bind Name}" />
</DataTemplate>
</NavigationView.MenuItemTemplate>
You could then easily get a reference to the MenuItem
source of the clicked item in the event handler by casting the InvokedItem
property of the NavigationViewItemInvokedEventArgs
:
private void OnItemInvoked(NavigationView sender, NavigationViewItemInvokedEventArgs args)
{
MenuItem menuItem = args.InvokedItem as MenuItem;
//access any properties of the clicked MenuItem here, e.g.:
string name = menuItem.Name;
}
Upvotes: 0
Reputation: 8681
But it seems slightly wrong, although I cannot think of better solution. Could someone help me out?
Actually, in the ItemInvoked
event, you could get an InvokedItem object directly from the NavigationViewItemInvokedEventArgs. And the InvokedItem object is the data that you used to bind to the NavigationViewMenuItem
.
For example,if I have NavigationViewMenuItem
template a like this:
<DataTemplate x:Key="NavigationViewMenuItem" x:DataType="local:TestMenuItem">
<NavigationViewItem Content="{x:Bind ItemName}" />
</DataTemplate>
And the TestMenuItem object like this:
public class TestMenuItem
{
public string ItemName { get; set; }
}
Then in the ItemInvoked
event, I could get get the value of the ItemName
property like this:
private void NavigationView_ItemInvoked(NavigationView sender, NavigationViewItemInvokedEventArgs args)
{
// directly get the item value
var item = args.InvokedItem as string;
switch (item)
{
case "AAA":
ContentFrame.Navigate(typeof(AAAPage));
break;
case "BBB":
ContentFrame.Navigate(typeof(BBBPage));
break;
case "CCC":
ContentFrame.Navigate(typeof(CCCPage));
break;
};
}
Upvotes: 0