ContextMenu中的绑定属性来自Parent的Parent的DataContext

时间:2015-02-25 11:18:10

标签: c# wpf xaml .net-4.0

我想在MenuItem容器中绑定ItemsControl中的属性。我有一个分层模型; Item类有一个SubItem列表。 ViewModel本身有一个Item列表(因此有两个ItemsControl,其中一个位于另一个ItemTemplate中。

我在SO上发现了其他几个问题(this one for instance),并且我了解到ContextMenu的可视树与其余部分分开了。

通过Tag属性“转移”模型的数据,我设法做到并且它有效(但感觉有点像hacky)。

这是两个模型类:

public class SubItem
{
    public int Current { get; set; }

    public Subitem(int current)
    {
        Current = current;
    }
}

public class Item
{
    public ObservableCollection<SubItem> SubItems { get; set; }

    public string Parent { get; set; }

    public Item(string Parent)
    {
        Parent = Parent;
        SubItems = new ObservableCollection<SubItem>();
    }
}

以下是视图模型:

public class ViewModel
{
    public ObservableCollection<Item> Items { get; set; } 

    public ViewModel()
    {
        Items = new ObservableCollection<Item>();
        FillData();
    }

    private void FillData()
    {
        //...
    }
}

这是页面根目录的ItemsControl(页面的DataContextViewModel类的实例):

<ItemsControl ItemsSource="{Binding Items}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <ItemsControl ItemsSource="{Binding SubItems}">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Current}"
                                   Tag="{Binding DataContext.Parent, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}, Mode=FindAncestor}}">
                            <TextBlock.ContextMenu>
                                <ContextMenu>
                                    <MenuItem Header="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}, Mode=FindAncestor}}"/>
                                </ContextMenu>
                            </TextBlock.ContextMenu>
                        </TextBlock>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

我的问题是:这是正确的方法吗?我尝试了许多其他方法来避免将属性绑定到Tag,但无法使其正常工作。

丑陋的部分具体是:

Tag="{Binding DataContext.Parent, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}, Mode=FindAncestor}}" 

其次是:

Header="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}, Mode=FindAncestor}}"

我认为这有点难看,我相信有更好的方法可以做到这一点。解决方案必须与.NET 4.0一起使用。

1 个答案:

答案 0 :(得分:1)

您需要在菜单的容器中添加标签,并使用展示位置目标绑定到该容器。

查看此示例:

<StackPanel x:Key="ConfigurationListItem" x:Shared="False" Tag="{Binding ElementName=UserControl}">
        <StackPanel Orientation="Horizontal">
            <Button>
                <Button.InputBindings>
                    <MouseBinding Gesture="LeftDoubleClick" Command="{Binding ElementName=UserControl, Path=LaunchCommand}" CommandParameter="{Binding}" />
                    <MouseBinding Gesture="LeftClick" Command="{Binding ElementName=UserControl, Path=SelectCommand}" CommandParameter="{Binding}" />
                </Button.InputBindings>
        </StackPanel>

        <StackPanel.ContextMenu>
            <ContextMenu DataContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}" Tag="{Binding}">
                <MenuItem Header="Sync Environment Dependencies" 
                        Command="{Binding Parent.PlacementTarget.Tag.SyncEnvironmentCommand, RelativeSource={RelativeSource Self}}"
                        CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}, Path=PlacementTarget.DataContext}" />
            </ContextMenu>
        </StackPanel.ContextMenu>
    </StackPanel>