Access ViewModel / DataConext inside ContextMenu
How can I get the original DataContext of the UserControl inside of a ContextMenu.
The code below, you can see that there is a Button in the DataTemplate, which binds correctly. However, when trying to bind the datasource of the contextmenu, I recieve the following error:
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.TreeView', AncestorLevel='1''. BindingExpression:Path=DataContext; DataItem=null; target element is 'ContextMenu' (Name=''); target property is 'DataContext' (type 'Object')
What do I need to do to allow the ContextMenu to bind to the ViewModel?
===============================================================================
The ViewModel is assigned to the datacontext of the view in the codebehind:
View:
<TreeView ItemsSource="{Binding Clients}"
cmd:TreeViewSelect.Command="{Binding SelectionChangedCommand}"
cmd:TreeViewSelect.CommandParameter="{Binding RelativeSource={RelativeSource Self},Path=SelectedItem}">
<TreeView.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Name}">
<TextBlock.ContextMenu>
<ContextMenu DataContext="{Binding DataContext,
RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TreeView}}}">
<MenuItem Header="{Binding TestString}" />
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
<Button DataContext="{Binding DataContext,
RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TreeView}}}"
Content="{Binding TestString}" Command="{Binding EditSelectedClientCommand}" />
</StackPanel>
</DataTemplate>
</TreeView.ItemTemplate>
</TreeView>
ViewModel:
public class ClientListViewModel : ViewModelBase
{
public String TestString {
get {
return "TESTING";
}
}
private ClientList _clients = null;
private readonly IClientService _clientService = null;
private readonly IEventAggregator _eventAggregator = null;
private Client _selectedClient = null;
private ICommand _selectionChangedCommand = null;
private ICommand _ed开发者_高级运维itSelectedClientCommand = null;
....
}
ContextMenus
do not appear in the visual tree which causes RelativeSource-bindings to fail, you can still get the DataContext
one way or another though. You could try this for example:
<TextBlock Text="{Binding Name}"
Tag="{Binding DataContext, RelativeSource={RelativeSource AncestorType=TreeView}}">
<TextBlock.ContextMenu>
<ContextMenu DataContext="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
<MenuItem Header="{Binding TestString}" />
<!-- ... --->
The PlacementTarget
is the TextBlock, and the DataContext
is tunneled through the Tag
. Just one way to do this (at least i hope it works), i have also seen some libraries which bridge this gap differently but i do not recall their origin...
精彩评论