2012-07-24 62 views
2

我在将一个命令绑定到compositecollection中的菜单项时遇到问题。 MenuItem是在UserControl.Resources中定义的ContextMenu的一部分。WPF在CompositeCollection中绑定MenuItem不起作用

问题是新标签的绑定不起作用。当我将MenuItem放在组合集合之外时,它将起作用。有任何想法吗?

<UserControl.Resources> 
    <ContextMenu x:Key="DataGridRowContextMenu"> 
     <MenuItem Header=" Set label"/> 
      <MenuItem.ItemsSource> 
        <CompositeCollection> 
          <CollectionContainer Collection="{Binding Source={StaticResource labelsSelectSource}}" /> 
        <MenuItem Header=" New label..." 
          Command="{Binding DataContext.NewLabel, 
           RelativeSource={RelativeSource Mode=FindAncestor, 
           AncestorType={x:Type UserControl}}}"/> 

         </CompositeCollection> 
       </MenuItem.ItemsSource> 
      </MenuItem> 
<UserControl.Resources/> 

回答

1

这是因为一个事实,即ContextMenu不在同一visual tree其包含的父,导致数据绑定的问题发生。由于ContextMenu不在同一个可视化树中,所以ElementName,RelativeSouceFindAncestor)等绑定将不起作用。

可以解决这个打通

  1. 后面的代码中的用户控件:使用PlacementTarget财产这样

    NameScope.SetNameScope(DataGridRowContextMenu, NameScope.GetNameScope(this)); 
    
  2. -

    <ContextMenu 
        x:Key="DataGridRowContextMenu"> 
        DataContext="{Binding PlacementTarget, RelativeSource={RelativeSource Self}}"> 
        . 
        . 
        . 
        <MenuItem 
         Header=" New label..."  
         Command="{Binding DataContext.NewLabel}"/> 
    

或者我们E的其他解决方案,从 -

ElementName Binding from MenuItem in ContextMenu

WPF: DataContext for ContextMenu

+0

有关如何在UserControl.Resources中使用DataGridRowContextMenu并使用Style绑定的任何建议?然后,x:Key名称在代码后面不可用。 – ferdyh 2012-07-26 11:34:09

+0

@Ferdy在这种情况下,您可以在代码中使用[FrameworkElement.FindResource](http://msdn.microsoft.com/zh-cn/library/system.windows.frameworkelement.findresource.aspx)方法,然后使用SetNamescope;也看看我的答案[这里](http://stackoverflow.com/questions/11333028/how-to-access-a-control-from-a-contextmenu-menuitem-via-the-visual-tree/11339065#11339065 )获取相关信息。 – akjoshi 2012-07-26 15:12:03

0

使用CommandTarget财产或使你的DataContext的staticRessource像

<MenuItem Header=" New label..." 
      Command="{Binding Path=NewLabel,Source={StaticResource viewModel}}"/> 
1

我一直有这个疯狂的文本菜单和其的MenuItems挣扎绕了长时间。但是我找到了一个解决方案,使用名为“Data”的依赖属性创建自定义行为“BindingProxyBehaviour”。这个属性包含一个对象,例如你的DataContext(如果你使用MVVM模式,也许是你的ViewModel)。

public class BindingProxyDataBehavior : Freezable 
{ 
    public static readonly DependencyProperty DataProperty = 
     DependencyProperty.Register("Data", typeof(object), typeof(BindingProxyDataBehavior), new UIPropertyMetadata(null)); 

    protected override Freezable CreateInstanceCore() 
    { 
     return new BindingProxyDataBehavior(); 
    } 

    public object Data 
    { 
     get { return (object)GetValue(DataProperty); } 
     set { SetValue(DataProperty, value); } 
    } 
} 

只需将BindingProxy添加为xaml文件中的资源就可以了。

<UserControl.Resources> 
    <ResourceDictionary> 
     <behaviors:BindingProxyDataBehavior x:Key="BindingProxyViewModel" Data="{Binding}"/> 
     <behaviors:BindingProxyDataBehavior x:Key="BindingProxyViewModelDynamicDataList" Data="{Binding DynamicDataListObject}"/> 
    </ResourceDictionary> 
</UserControl.Resources> 

在我的情况我使用CompositeCollection来混合静态和动态MenuItems。因此使用键“BindingProxyViewModelDynamicDataList”的第二个资源。

现在您可以轻松访问您的数据,无论您的ContextMenu在哪里。 我在xaml树中的ContexMenu位置是UserControl-> Grid-> DataGrid-> DataGridTemplateColumn-> CellTemplate-> DataTemplate-> TextBox.Template-> Grid-> TextBlock-> controls:IconButton(从按钮派生的简单的customButton控件),在这里我们在IconButton里面:

<controls:IconButton.ContextMenu> 
<ContextMenu x:Name="AnyContextMenuName"> 
    <ContextMenu.Resources> 
     <HierarchicalDataTemplate DataType="{x:Type DynamicDataListItemType}"> 
      <TextBlock Text="{Binding DynamicDataListItemProperty}"/> 
     </HierarchicalDataTemplate> 
    </ContextMenu.Resources> 
    <ContextMenu.ItemsSource> 
     <CompositeCollection> 
      <CollectionContainer Collection="{Binding Source={StaticResource BindingProxyViewModelDynamicDataList}, Path=Data}"/> 
      <Separator/> 
      <MenuItem Header="Your static header" Command="{Binding Source={StaticResource BindingProxyViewModel}, Path=Data.ViewModelCommandForYourStaticMenuItem}"/> 
     </CompositeCollection> 
    </ContextMenu.ItemsSource> 
    <ContextMenu.ItemContainerStyle> 
     <Style> 
      <Setter Property="MenuItem.Foreground" Value="{DynamicResource DefaultForegroundBrush}"/> 
      <Setter Property="MenuItem.Command" Value="{Binding Source={StaticResource BindingProxyViewModel}, Path=Data.ViewModelCommandForDynamicMenuItems}"/> 
      <Setter Property="MenuItem.CommandParameter" Value="{Binding}"/> 
     </Style> 
    </ContextMenu.ItemContainerStyle> 
</ContextMenu> 
</controls:IconButton.ContextMenu> 

我希望我可以帮助这个短的帖子sombody。