C
C#3mo ago
stigzler

✅ WPF - Accessing a TreeViewItem's root UserControl DataContext for a Command

I am trying to execute a Command which exists in the ViewModel bound to the root parent UserControl of a child TreeViewItem. This is from a ContextMenu bound to root TreeViewItems. The TreeView code: Key code:
<StackPanel.ContextMenu>
<ContextMenu Style="{StaticResource ContextMenu}">
<MenuItem Header="Delete Gist" Background="{DynamicResource {x:Static vsshell:VsBrushes.WindowKey}}"
Style="{StaticResource MenuItem}"
Command="{Binding
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type viewmodels:MainWindowViewModel}},
Path=DataContext.DeleteGistCMD}">
<MenuItem.Icon>
<imaging:CrispImage Moniker="{x:Static catalog:KnownMonikers.DeleteListItem}"/>
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</StackPanel.ContextMenu>
<StackPanel.ContextMenu>
<ContextMenu Style="{StaticResource ContextMenu}">
<MenuItem Header="Delete Gist" Background="{DynamicResource {x:Static vsshell:VsBrushes.WindowKey}}"
Style="{StaticResource MenuItem}"
Command="{Binding
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type viewmodels:MainWindowViewModel}},
Path=DataContext.DeleteGistCMD}">
<MenuItem.Icon>
<imaging:CrispImage Moniker="{x:Static catalog:KnownMonikers.DeleteListItem}"/>
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</StackPanel.ContextMenu>
Broader context: https://paste.mod.gg/khruicdqkfhy/1 MainWindowViewModel is the DataContext of MainWindow, within which the Command I'm targeting exists. I've tried various permutations of RelativeSource for Binding, as despite xaml intellisense suggesting the binding is right by offering the command as an option, it doesn't fire on selecting the relevant ContextMenuItem. Any ideas?
BlazeBin - khruicdqkfhy
A tool for sharing your source code with the world!
1 Reply
stigzler
stigzler3mo ago
You can use a markupextension:
using System;
using System.Windows.Controls;
using System.Windows.Markup;
using System.Xaml;

[MarkupExtensionReturnType(typeof(ContentControl))]
public class RootObject : MarkupExtension
{
public override object ProvideValue(IServiceProvider serviceProvider)
{
var rootObjectProvider = (IRootObjectProvider)serviceProvider.GetService(typeof(IRootObjectProvider));
return rootObjectProvider?.RootObject;
}
}
using System;
using System.Windows.Controls;
using System.Windows.Markup;
using System.Xaml;

[MarkupExtensionReturnType(typeof(ContentControl))]
public class RootObject : MarkupExtension
{
public override object ProvideValue(IServiceProvider serviceProvider)
{
var rootObjectProvider = (IRootObjectProvider)serviceProvider.GetService(typeof(IRootObjectProvider));
return rootObjectProvider?.RootObject;
}
}
It lets you do:
<ItemsControl ItemsSource="{Binding Markers}">
...
<ContextMenu DataContext="{Binding DataContext, Source={local:RootObject}}">
<MenuItem Header="Edit"
Command="{Binding EditCommand}" />
</ContextMenu>
...
</ItemsControl>
<ItemsControl ItemsSource="{Binding Markers}">
...
<ContextMenu DataContext="{Binding DataContext, Source={local:RootObject}}">
<MenuItem Header="Edit"
Command="{Binding EditCommand}" />
</ContextMenu>
...
</ItemsControl>
From: https://stackoverflow.com/a/33485960/3472225
Stack Overflow
WPF ContextMenu woes: How do I set the DataContext of the ContextMenu?
I am having some trouble figuring out how to set the correct DataContext on a ContextMenu. I have a collection of view models who are the source of an ItemsControl. Each view model has a collect...