Command和CommandParameter的不同Datacontext

时间:2012-07-12 07:53:57

标签: wpf binding command contentcontrol commandparameter

是否可以为WPF DatacontextCommand设置不同的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>

我想将ListGrid的Binding冒泡到另一个Viewmodel,将Command冒充到本地ViewModel。但CommandParameter应该是ContentControl。 LOG说:

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')

2 个答案:

答案 0 :(得分:2)

ContextMenu打破了DataContext继承链,这就是无法找到ElementName=currentContent的原因。

在此处查看artificial inheritance context并使用课程DataContextSpy

然后执行以下操作:

<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>

答案 1 :(得分:1)

ContextMenu有一个单独的VisualTree,并且不属于UserControl的VisualTree,这就是为什么Elementname绑定不起作用的原因。使用ElementName绑定的简单解决方法是在UserControl的代码隐藏中添加它

NameScope.SetNameScope(currentContent, NameScope.GetNameScope(this)); 

或者您可以使用Enable ElementName Bindings with ElementSpy