0

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?

Massimiliano Kraus
  • 3,638
  • 5
  • 27
  • 47
Maslow
  • 18,464
  • 20
  • 106
  • 193
  • 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 ` ...` – 15ee8f99-57ff-4f92-890c-b56153 Sep 28 '16 at 15:39
  • 1
    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. https://stackoverflow.com/questions/15033522/wpf-contextmenu-woes-how-do-i-set-the-datacontext-of-the-contextmenu – Bradley Uffner Sep 28 '16 at 17:30
  • 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 Sep 28 '16 at 17:54
  • 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 Sep 30 '16 at 15:04
  • @EdPlunkett I thought that one was going to work, it did not =( – Maslow Oct 03 '16 at 12:44
  • @Maslow try defining the listboxitem style in ListBox.Resources – 15ee8f99-57ff-4f92-890c-b56153 Oct 03 '16 at 12:47
  • @Grx70 that gave me a System.Window.Markup.XamlParseException that shared attribute in namespace ... can only be used in compiled resource dictionaries . and yes I'm aware of the context menu visual parent problem. – Maslow Oct 03 '16 at 12:57
  • when I stopped using my custom listbox, the context menu worked, but it works better with @EdPlunkett 's suggestion to `` – Maslow Oct 03 '16 at 13:29

1 Answers1

0

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.

Maslow
  • 18,464
  • 20
  • 106
  • 193