开发者

Using different databinding sources within ListBox and ContextMenus

Here is the 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>

Ok so the ListBox's ItemSource is bound to the Documents collection in the VM and properly renders the Titles and IDs

The Context Menu's ItemSource is bound to the CategoryList collection in the VM and properly renders the list of categories.

The problem I have is with the Command Binding:

Command="{Binding AddDocumentToCategoryContextMenuCommand}"

Since the ItemSource for the ContextMenu is already set, it tries to get the AddDocumentToCategoryContextMenuCommand from CategoryList. Obviously the command is not there, it is a member of the VM.

I do not want any references to the VMs or Models in the XAML. Everything is constructed using Unity and VM-View is associated in 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>

How can I databind to a member of the VM from within the ContextItem.

Thanks.

UPDATED edit #1 starts Here

Here is the updated xaml (but still not working but some insight gained):

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

I have this example working for a simple example that does not use a ContextMenu. It appears that the ContextMenu (even though attached to the ListBox) is not part of the user control visual tree. The binding always comes back null / not found. I think the ContextMenu, because it is a floating "window" is constructed in its own tree and therefore cannot find the ListBox call "Results" in order to access the ListBox's DataContext.

Any thoughts on this? Any recommendations on how deal with?

Edit #2 Starts Here

In case you are are wondering, figured out the answer to the binding question:

This binding works:

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

Hope this helps others with the same question.

One last update for completeness.

In order for the command to know which context menu item was clicked on, I had to change the xaml slightly (silly oversight):

                <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>
开发者_Python百科

Again, hope this helps others.


Use the ElementName property of the binding to specify that. You'd end up with something like this:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜