3

我在将命令绑定到复合集合中的菜单项时遇到问题。MenuItemContextMenu其中定义的一部分UserControl.Resources

问题是新标签的绑定不起作用。当我将 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/>
4

3 回答 3

1

发生这种情况是因为ContextMenuvisual tree与其包含的父级不同,从而导致数据绑定问题。由于ContextMenu不在同一个可视化树中,ElementNameRelativeSouce( FindAncestor) 等绑定将不起作用。

你可以解决这个问题

  1. 在 UserControl 后面的代码中:

    NameScope.SetNameScope(DataGridRowContextMenu, NameScope.GetNameScope(this)); 
    
  2. 使用这样的PlacementTarget属性 -

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

或使用其他解决方案 -

ContextMenu 中 MenuItem 的 ElementName 绑定

WPF:上下文菜单的数据上下文

于 2012-07-25T10:10:17.230 回答
1

我一直在为这个疯狂的 ContextMenu 及其 MenuItems 苦苦挣扎。但是我找到了一个解决方案来使用它创建一个自定义行为“BindingProxyBehaviour”,它的依赖属性名为“Data”。此属性包含一个对象,例如您的 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(simple customButton control derived from button) 在这里我们位于 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>

我希望我可以通过这篇短文帮助某人。

于 2015-08-20T07:45:34.113 回答
0

使用CommandTarget属性或为您的数据上下文创建一个 staticRessource,例如

<MenuItem Header=" New label..." 
          Command="{Binding Path=NewLabel,Source={StaticResource viewModel}}"/>
于 2013-01-08T16:57:37.553 回答