Reputation: 1535
Let’s say I have a ListView
, a DataTemplate
for the items and two MenuFlyout
s:
<Page>
<Page.Resources>
<MenuFlyout x:Key="Menu1" />
<MenuFlyout x:Key="Menu2" />
<DataTemplate x:Key="Template"
x:DataType="local:MyItem">
<TreeViewItem>
<Grid ContextFlyout="{StaticResource Menu1}">
</Grid>
</TreeViewItem>
</DataTemplate>
<TreeViewItem
</Page.Resources>
<ListView ItemTemplate="{StaticResource Template}"
Items="{x:Bind ...}"
</Page>
So each item in the ListView
has a context/right-click menu set to Menu1.
Now, let's say I want to have a different context menu for some of the items in the ListView
, e.g., Menu2. How can I accomplish this?
In other words, how do I switch the ContextFlyout
to MenuFlyout
Menu2 for certain MyItem
items in the ListView
based on values of properties in the MyItem
type?
I wasn't specifying the question completely. Obviously, to accomplish that you would bind the to the ContextFlyout
. This was not my question.
In my case I cannot do that because:
ItemSource
of a ListView
/TreeView
/etc,So I need to find a way in the UI layer to hook in to each item provided by the view model and then set the ContextMenu
based on the properties of that item.
The question becomes: how to, in the UI layer (e.g., a Page
or its code behind), change a value (which is not bound to the view model, it's a resource in the UI layer) within a DataTemplate
, based on the current bound item?
I've also looked at ContextRequested
but the docs recommend setting the ContextFlyout
property instead.
I hope this makes my question clearer.
The only way I can think of how to do it is in a DataTemplateSelector
:
<MenuFlyout x:Key="MenuFlyout1">
<MenuFlyoutItem Command="{x:Bind ViewModel.Command1}"
CommandParameter="{Binding}"
Text="1">
</MenuFlyoutItem>
</MenuFlyout>
<MenuFlyout x:Key="MenuFlyout2">
<MenuFlyoutItem Command="{x:Bind ViewModel.Command2}"
CommandParameter="{Binding}"
Text="2">
</MenuFlyoutItem>
</MenuFlyout>
<DataTemplate x:Key="MyDataTemplate"
x:DataType="local:MyItem">
<TreeViewItem />
</DataTemplate>
<local:MyTemplateSelector x:Key="Selector"
MenuFlyout1="{StaticResource MenuFlyout1}"
MenuFlyout2="{StaticResource MenuFlyout2}"
MyDataTemplate="{StaticResource MyDataTemplate}" />
public class MyTemplateSelector : DataTemplateSelector
{
public MyDataTemplate Template { get; set; } = null!;
public MenuFlyout MenuFlyout1 { get; set; } = null!;
public MenuFlyout MenuFlyout2 { get; set; } = null!;
protected override DataTemplate? SelectTemplateCore(object item)
{
MenuFlyout menuToUse;
if (item.Type == 1)
menu = MenuFlyout1;
else
menu = MenuFlyout2;
// How to assign menu to `Template` ?
return Template;
}
}
But I cannot manage to assign the menu to the Template
. It've tried
var treeViewItem = Template.GetElement(new());
treeViewItem.ContextFlyout = MenuFlyout1;
but it has no effect.
Upvotes: 0
Views: 225
Reputation: 2130
I can make Resource dictionaries with {x:Bind} work and cannot override the resource key but you can get a workaround from https://learn.microsoft.com/en-us/answers/questions/1465387/generic-xaml-x-bind-with-converter-binding.
TemplatesResourceDictionary.xaml
<?xml version="1.0" encoding="utf-8"?>
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="App1.TemplatesResourceDictionary"
xmlns:local="using:App1">
<DataTemplate x:Key="EmployeeTemplate" x:DataType="local:IEmployee">
<Grid Background="{x:Bind Color}">
<TextBlock Text="{x:Bind Name}" Foreground="{StaticResource MyBrush}"/>
</Grid>
</DataTemplate>
</ResourceDictionary>
TemplatesResourceDictionary.xaml.cs
namespace App1
{
public partial class TemplatesResourceDictionary
{
public TemplatesResourceDictionary()
{
this.InitializeComponent();
}
}
}
IEmployee
class IEmployee
{
public IEmployee(string n, Brush b)
{
Name = n;
Color = b;
}
public string Name;
public Brush Color;
}
App.xaml
<?xml version="1.0" encoding="utf-8"?>
<Application
x:Class="App1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App1">
<Application.Resources>
<ResourceDictionary>
<SolidColorBrush x:Key="MyBrush" Color="Red" />
<ResourceDictionary.MergedDictionaries>
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
<!-- Other merged dictionaries here -->
<local:TemplatesResourceDictionary/>
</ResourceDictionary.MergedDictionaries>
<!-- Other app resources here -->
</ResourceDictionary>
</Application.Resources>
</Application>
MainWindow.xaml
<StackPanel>
<StackPanel.Resources>
<Color x:Key="MyBrush">Black</Color>
</StackPanel.Resources>
<ListView ItemsSource="{x:Bind Employees}" ItemTemplate ="{StaticResource EmployeeTemplate}">
<ListView.Resources>
<Color x:Key="MyBrush">Green</Color>
</ListView.Resources>
</ListView>
<ListView ItemsSource="{x:Bind Employees}" ItemTemplate ="{StaticResource EmployeeTemplate}">
</ListView>
</StackPanel>
Upvotes: 1