0
votes

I have a style that doesn't seem to be working. In spite of Snoop telling me the DataContext for the ListBoxItem is correct, nothing shows up. If it was a problem with the binding for Commands I would expect to see an empty context menu appear.

The style:

<ContextMenu x:Key="CommandsContextMenu" ItemsSource="{Binding Commands}">
    <Style TargetType="MenuItem">
        <Setter Property="Header" Value="{Binding Name}"/>
    </Style>
</ContextMenu>

<Style TargetType="ListBoxItem">
    <Setter Property="ContextMenu" Value="{StaticResource CommandsContextMenu}" />
    <Style.Triggers>
        <DataTrigger Value="True">
            <DataTrigger.Binding>
                <Binding Path="DataContext.HasCommands" />
            </DataTrigger.Binding>
        </DataTrigger>
    </Style.Triggers>
</Style>

The snoop DataContext:

SnoopDataContext

The snoop properties showing the ContextMenu property isn't even set.

SnoopProperties

The idea here, was that without knowing any of the types, I could have a listbox item style where if the thing it was bound to has a property called HasCommands, and it was set to true, then it would set a context menu on that listbox item, bound to the Commands property.

I'm not getting any binding errors or warnings from PresentationTraceSources.DataBindingSource

Why doesn't the context menu get set?

1
Oh, wait -- I'm sorry, I just skimmed your question. I think the only problem you may have here is simply where the menu item style is defined. It's in the content, where it'll be ignored. Try putting it in <ContextMenu><ContextMenu.ItemContainerStyle><Style TargetType="MenuItem" .../> ... - 15ee8f99-57ff-4f92-890c-b56153
Context menus are not connected to the visual tree of their "parent". That means they don't inherit the DataContext. See this question for a few ways to work around it. stackoverflow.com/questions/15033522/… - Bradley Uffner
One potential problem that I see here is that your ContextMenu is defined as a resource. By default, only one instance is created and then returned upon every fetch from the dictionary, resulting in this single instance being set as the context menu of multiple elements, which I think might be the cause of your problems. Try setting x:Shared="False" on it in order to ensure a new instance is created every time the resource is fetched from the dictionary. Also, @BradleyUffner comment is useful and probably it'll be the next problem you'll encounter. - Grx70
all the comments seem to me to be things that would prevent the menu(s) from having items, or from having distinct items, not things that would prevent a context menu from ever being set for any of them. However, I'll give them a try - Maslow
@EdPlunkett I thought that one was going to work, it did not =( - Maslow

1 Answers

0
votes

So it turns out, that the problem was using something that inherited from ListBox

for reference here's my defined class:

// adapted from http://stackoverflow.com/questions/3350187/wpf-c-rearrange-items-in-listbox-via-drag-and-drop
// which was probably adapted from http://wpftutorial.net/DragAndDrop.html
type DragDropListBox() as self =
    inherit ListBox()

which from there only hooks the following

  • self.PreviewMouseLeftButtonUp
  • self.PreviewMouseMove
  • override x.OnItemsSourceChanged

and in the intialization it overwrites the ItemContainerStyle as follows:

So it turns out, that the problem was using something that inherited from ListBox

for reference here's the top of my class:

// adapted from http://stackoverflow.com/questions/3350187/wpf-c-rearrange-items-in-listbox-via-drag-and-drop
// which was probably adapted from http://wpftutorial.net/DragAndDrop.html
type DragDropListBox() as self =
    inherit ListBox()

which from there only hooks the following

  • self.PreviewMouseLeftButtonUp
  • self.PreviewMouseMove
  • override x.OnItemsSourceChanged

and in the intialization it overwrites the ItemContainerStyle as follows:

do
    self.PreviewMouseLeftButtonUp.Add listBoxPreviewMouseLeftButtonUp
    //self.PreviewMouseLeftButtonDown.Add listBoxPreviewMouseMove //.AddHandler (MouseButtonEventHandler previewMouseMove)
    self.PreviewMouseMove.Add listBoxPreviewMouseMove
    let style =
        let s = Style(typeof<ListBoxItem>)
        s.Setters.Add (Setter(ListBoxItem.AllowDropProperty, true))
        s.Setters.Add (EventSetter(ListBoxItem.PreviewMouseLeftButtonDownEvent, MouseButtonEventHandler listBoxPreviewMouseLeftButtonDown))
        s.Setters.Add (EventSetter(ListBoxItem.DropEvent, DragEventHandler listBoxItemDrop))

        s
    self.ItemContainerStyle <- style

now I've got to figure out if you can add two styles together.