问题
Is it possible to have a different Datacontext
for a WPF Command
and a CommandParameter
?
<UserControl>
<UserControl.Resources>
<viewmodels:ListViewGridBaseViewModel x:Key="vm" />
</UserControl.Resources>
<Grid>
<ContentControl x:Name="currentContent"
Content="{Binding Path=ListGrid}" >
<ContentControl.ContextMenu>
<ContextMenu >
<MenuItem Command="{Binding Path=Save}"
CommandParameter="{Binding ElementName=currentContent}"
DataContext="{StaticResource ResourceKey=vm}"
Header="Save">
<MenuItem.Icon>
<Image Source="{StaticResource ResourceKey=Save}"
Height="16"
Width="16"/>
</MenuItem.Icon>
</MenuItem>
<MenuItem Command="{Binding Path=Revert}"
DataContext="{StaticResource ResourceKey=vm}"
Header="Revert">
<MenuItem.Icon>
<Image Source="{StaticResource ResourceKey=Revert}"
Height="16"
Width="16"/>
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</ContentControl.ContextMenu>
</ContentControl>
</Grid>
</UserControl>
I want the Binding
for ListGrid bubbled up to another Viewmodel and the Command
to a local ViewModel. But the CommandParameter
should be the ContentControl
.
LOG is saying:
System.Windows.Data Error: 4 : Cannot find source for binding with
reference 'ElementName=currentContent'. BindingExpression:(no path);
DataItem=null; target element is 'MenuItem' (Name='');
target property is 'CommandParameter' (type 'Object')
回答1:
ContextMenu
breaks the DataContext
inheritance chain, that's why ElementName=currentContent
cannot be found.
Look here for artificial inheritance context and use the class DataContextSpy
then do the following:
<UserControl>
<UserControl.Resources>
<viewmodels:ListViewGridBaseViewModel x:Key="vm" />
<local:DataContextSpy DataContext="{Binding ElementName=currentContent}" x:Key="Spy">
</UserControl.Resources>
<Grid>
<ContentControl x:Name="currentContent"
Content="{Binding Path=ListGrid}" >
<ContentControl.ContextMenu>
<ContextMenu >
<MenuItem Command="{Binding Path=Save}"
CommandParameter="{Binding DataContext,Source={StaticResource Spy}}"
DataContext="{StaticResource ResourceKey=vm}"
Header="Save">
<MenuItem.Icon>
<Image Source="{StaticResource ResourceKey=Save}"
Height="16"
Width="16"/>
</MenuItem.Icon>
</MenuItem>
<MenuItem Command="{Binding Path=Revert}"
DataContext="{StaticResource ResourceKey=vm}"
Header="Revert">
<MenuItem.Icon>
<Image Source="{StaticResource ResourceKey=Revert}"
Height="16"
Width="16"/>
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</ContentControl.ContextMenu>
</ContentControl>
</Grid>
</UserControl>
回答2:
The ContextMenu
has a separate VisualTree
and is not part of UserControl's VisualTree
and that's why Elementname
binding's won't work. A simple workaround to use ElementName
bindings is to add this in your UserControl's code-behind
NameScope.SetNameScope(currentContent, NameScope.GetNameScope(this));
Or you can use Enable ElementName Bindings with ElementSpy
来源:https://stackoverflow.com/questions/11447343/different-datacontext-for-command-and-commandparameter