在ListBox和ContextMenus中使用不同的数据绑定源

时间:2011-03-09 18:29:50

标签: xaml data-binding listbox contextmenu command-pattern

这是XAML:

                <ListBox ItemsSource="{Binding Documents}" BorderBrush="{x:Null}">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Vertical">
                            <TextBlock Text="{Binding Title}" FontSize="12" FontWeight="Bold" />
                            <TextBlock Text="{Binding ID}" FontSize="10" FontStyle="Italic" />
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>

                <ListBox.ContextMenu>
                    <ContextMenu ItemsSource="{Binding CategoryList}">
                        <ContextMenu.ItemTemplate>
                            <DataTemplate>
                                <MenuItem Command="{Binding AddDocumentToCategoryContextMenuCommand}" Header="{Binding Category.Name}" />
                            </DataTemplate>
                        </ContextMenu.ItemTemplate>
                    </ContextMenu>
                </ListBox.ContextMenu>

            </ListBox>

好的,所以ListBox的ItemSource绑定到VM中的Documents集合并正确呈现标题和ID

Context Menu的ItemSource绑定到VM中的CategoryList集合,并正确呈现类别列表。

我遇到的问题是命令绑定:

Command="{Binding AddDocumentToCategoryContextMenuCommand}"

由于已经设置了ContextMenu的ItemSource,它会尝试从CategoryList获取AddDocumentToCategoryContextMenuCommand。显然命令不存在,它是VM的成员。

我不希望在XAML中引用任何VM或模型。一切都是使用Unity构建的,VM-View与App.xaml相关联:

<Application.Resources>
    <DataTemplate DataType="{x:Type vms:FeedViewModel}">
        <views:FeedView/>
    </DataTemplate>
    <DataTemplate DataType="{x:Type vms:DocumentsViewModel}">
        <views:DocumentsView/>
    </DataTemplate>
    <DataTemplate DataType="{x:Type vms:ManagementViewModel}">
        <views:ManagementView/>
    </DataTemplate>
    <DataTemplate DataType="{x:Type dev:DevelopmentViewModel}">
        <dev:DevelopmentView />
    </DataTemplate>
</Application.Resources>

如何从ContextItem中数据绑定到VM的成员。

感谢。

更新编辑#1从此处开始

这是更新的xaml(但仍然没有工作,但获得了一些见解):

<ListBox ItemsSource="{Binding Documents}" x:Name="Results" BorderBrush="{x:Null}">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Vertical">
                            <TextBlock Text="{Binding Title}" FontSize="12" FontWeight="Bold" />
                            <TextBlock Text="{Binding ID}" FontSize="10" FontStyle="Italic" />
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>

                <ListBox.ContextMenu>
                    <ContextMenu ItemsSource="{Binding CategoryList}">
                        <ContextMenu.ItemTemplate>
                            <DataTemplate>
                                <MenuItem Command="{Binding ElementName=Results, Path=DataContext.AddDocumentToCategoryContextMenuCommand}" Header="{Binding Category.Name}" />
                            </DataTemplate>
                        </ContextMenu.ItemTemplate>
                    </ContextMenu>
                </ListBox.ContextMenu>

            </ListBox>

我让这个例子用于一个不使用ContextMenu的简单示例。看起来ContextMenu(即使附加到ListBox)不是用户控件可视树的一部分。绑定总是返回null /找不到。我认为ContextMenu,因为它是一个浮动的“窗口”是在它自己的树中构造的,因此无法找到ListBox调用“Results”以访问ListBox的DataContext。

对此有何想法?关于如何处理的任何建议?

编辑#2从这里开始

如果你想知道,找出了绑定问题的答案:

此绑定有效:

Command="{Binding RelativeSource={RelativeSource AncestorType=ContextMenu}, Path=PlacementTarget.DataContext.AddDocumentToCategoryContextMenuCommand}

希望这可以帮助其他人解决同样的问题。

完整性的最后一次更新。

为了让命令知道点击了哪个上下文菜单项,我不得不稍微改变xaml(愚蠢的疏忽):

                <ListBox.ContextMenu>
                    <ContextMenu x:Name="Context" ItemsSource="{Binding CategoryList}">
                        <ContextMenu.ItemTemplate>
                            <DataTemplate>
                                <MenuItem Command="{Binding RelativeSource={RelativeSource AncestorType=ContextMenu}, Path=PlacementTarget.DataContext.AddDocumentToCategoryContextMenuCommand}"  
                                            CommandParameter="{Binding Category.ID}"
                                            Header="{Binding Category.Name}" />
                            </DataTemplate>
                        </ContextMenu.ItemTemplate>
                    </ContextMenu>
                </ListBox.ContextMenu>

再次,希望这有助于其他人。

1 个答案:

答案 0 :(得分:2)

使用ElementName property of the binding指定。你最终会得到这样的东西:

Command="{Binding ElementName=ViewModelObject 
                  Path=AddDocumentToCategoryContextMenuCommand}"