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 tryMaslow
@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.