I have this style into ResourceDictionary. This is a ToggleButton´s list. I add a contextMenu to each button and I want to hand into the viewmodel the click event. I have the method Editindicator into viewmodel. When I run the project and i click over contextmenu item it broke and show this error "{"No target found for method Click."}". I think that this error is owing to menuitem has lost viewmodel´s datacontext.
Can anyone help here? Thanks a lot in advice.
<Style x:Key="ListBoxStyleIndicador" TargetType="{x:Type ListBoxItem}">
<Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
<Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
<Setter Property="Padding" Value="2,0,2,0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate x:Name="ListBoxStyleIndicadorTemplate" TargetType="{x:Type ListBoxItem}">
<Border x:Name="Bd"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
Padding="{TemplateBinding Padding}"
SnapsToDevicePixels="true">
<Controles:ToggleButtonIndicador
Content="{Binding NombreIndicador}"
IdBIIndicadores="{Binding IdBiIndicadores}"
IsChecked="{Binding IsSelected, Mode=TwoWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}"
Style="{DynamicResource BotonNegro}"
Padding="6,2"
ToolTip="{Binding Descripcion}">
<Controles:ToggleButtonIndicador.ContextMenu >
<ContextMenu>
<MenuItem Header="Editar">
<MenuItem.Icon>
<Image Source="{DynamicResource ImagenBotonEditar}" />
</MenuItem.Icon>
<Interactivity:Interaction.Triggers>
<Interactivity:EventTrigger EventName="Click">
<cal:ActionMessage MethodName="EditIndicator" />
</Interactivity:EventTrigger>
</Interactivity:Interaction.Triggers>
</MenuItem>
</ContextMenu>
</Controles:ToggleButtonIndicador.ContextMenu>
</Controles:ToggleButtonIndicador>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="IsSelected" Value="{Binding Seleccionado, Mode=TwoWay}"/>
</Style>
Since ContextMenu is not a part of your Visual tree, you won't get reference to the DataContext of your ViewModel which is set for your UserControl. There are two ways to get the datacontext for your control -
Set explicitly dataContext for your ContextMenu using the PlacementTarget. Look at my answer here - cannot set tooltip in style
Use Proxy binding. Look at my answer here - Binding from items in ItemsControl to ItemControl's DataContext
Edit : For DataContext you can do like this -
<Controles:ToggleButtonIndicador Tag="{Binding DataContext, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}>
<Controles:ToggleButtonIndicador.ContextMenu >
<ContextMenu DataContext={Binding PlacementTarget.Tag, RelativeSource={RelativeSource Self}}>
<MenuItem Header="Editar">
<MenuItem.Icon>
<Image Source="{DynamicResource ImagenBotonEditar}" />
</MenuItem.Icon>
<Interactivity:Interaction.Triggers>
<Interactivity:EventTrigger EventName="Click">
<cal:ActionMessage MethodName="EditIndicator" />
</Interactivity:EventTrigger>
</Interactivity:Interaction.Triggers>
</MenuItem>
</ContextMenu>
</Controles:ToggleButtonIndicador.ContextMenu>
</Controles:ToggleButtonIndicador>
I am assumsing that your viemodel is binded to DataContext property of your UserControl.
In case it might help anyone. Before using the following example code, it is highly recommended to read Attaching a Virtual Branch to the Logical Tree in WPF on CodeProject. You would know why the problem occurs and how to solve it elegantly.
Here is the quick example.
// Add a DataContextBridge.
<UserControl.Resources>
<FrameworkElement x:Key="DataContextBridge" />
</UserControl.Resources>
// Bind.
<UserControl.DataContext>
<Binding
Mode="OneWayToSource"
Path="DataContext"
Source="{StaticResource DataContextBridge}" />
</UserControl.DataContext>
// Trigger a click event.
<ContextMenu>
<MenuItem>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ei:CallMethodAction
TargetObject="{Binding Source={StaticResource DataContextBridge}, Path=DataContext}"
MethodName="OnClick" />
</i:EventTrigger>
</i:Interaction.Triggers>
</MenuItem>
</ContextMenu>
Thanks.
Related
I cannot find the correct binding for a ContextMenu menu item in my custom control.
<ContextMenu x:Key="MyContextMenu">
<MenuItem Header="MyMenuItem"
Command="{Binding PlacementTarget.MyCommand, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}"/>
</ContextMenu>
<Style TargetType="{x:Type local:MyControl}" x:Shared="False">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MyControl}">
<DockPanel ContextMenu="{StaticResource MyContextMenu}">
<!--some controls-->
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
MyCommand is defined in MyControl.xaml.cs and is the command I wish to bind to the menu item.
The binding in the example looks for MyCommand in DockPanel. What is the correct binding?
You need to add a tag to the menu's container and bind to it using placement target.
View this example:
<StackPanel x:Key="ConfigurationListItem" x:Shared="False" Tag="{Binding ElementName=UserControl}">
<StackPanel.ContextMenu>
<ContextMenu DataContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}" Tag="{Binding}">
<MenuItem Header="Sync Environment Dependencies"
Command="{Binding Parent.PlacementTarget.Tag.SyncEnvironmentCommand, RelativeSource={RelativeSource Self}}"
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}, Path=PlacementTarget.DataContext}" />
</ContextMenu>
</StackPanel.ContextMenu>
</StackPanel>
Mr. Nimrod's answer didn't quite solve my problem, but provided a technique for doing so. Below is what worked.
The problem with ContextMenu is that you cannot use RelativeSource to traverse the element tree to an arbitrary control: you can only go as far as its container (which you refer to with PlacementTarget).
The basic strategy is to assign Tag in the ContextMenu's container. Tag refers to whatever control, command, etc. you are interested in. In my case I assigned it to TemplatedParent, which allowed me to bind to the MenuItem.Command to MyCommand.
<Style TargetType="{x:Type local:MyControl}" x:Shared="False">
<Style.Resources>
<ResourceDictionary>
<ContextMenu x:Key="MyContextMenu">
<MenuItem Header="MyItem"
Command="{Binding Parent.PlacementTarget.Tag.MyCommand, RelativeSource={RelativeSource Self}}"/>
</ContextMenu>
</ResourceDictionary>
</Style.Resources>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MyControl}">
<DockPanel ContextMenu="{StaticResource MyContextMenu}" Tag="{Binding RelativeSource={RelativeSource TemplatedParent}}">
<!--some controls-->
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
ContextMenu is not contained in VisualTree. hence no datacontext..
do this to have it working ..
<MenuItem Command="{Binding Path=PlacementTarget.DataContext.MyCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}" />
Following is the section from My Shell:
<StackPanel x:Name="stack" Orientation="Horizontal" Height="25" HorizontalAlignment="Right" Margin="0,4,0,0" Grid.Row="0">
<Button DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type StackPanel}}, Path=DataContext}" Content="Back" prism:Click.Command="{Binding Path=GoBackCommand}"/>
<Button DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type StackPanel}}, Path=DataContext}" Content="Forward" prism:Click.Command="{Binding Path=GoForwardCommand}" Margin="10,0,0,0"/>
</StackPanel>
<ContentControl x:Name="ActionContent" prism:RegionManager.RegionName="{x:Static inf:RegionNames.WorkspaceRegion}" Grid.Row="1">
<ContentControl.Template>
<ControlTemplate TargetType="ContentControl" >
<Grid >
<Controls:RoundedBox/>
<ContentPresenter Margin="10,0,10,0" Content="{TemplateBinding Content}" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="HasContent" Value="false">
<Setter Property="Visibility" Value="Collapsed" />
</Trigger>
<DataTrigger Binding="{Binding ElementName=stack}">
<Setter Property="DataContext" Value="{Binding RelativeSource={RelativeSource Self},
Path=Content.DataContext}" />
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</ContentControl.Template>
In ContentControl views are injecting from Modules (using ribbon tab). I want two button inside StackPanel may use ViewModels (DataContext) of injected views, for backward and Forward navigation.
Please Help, thanks!
I would start by having a good read at Prism Navigation Chapter,
and how to use the navigation journal.
Edit:
I don't think you can do what you want directly in XAML, but i can see 2 workarounds:
Define the commands as global CompositeCommand in the shell viewmodel, then have your views reister and unregister their own implementations as they are navigated.
Define a new Region in wich the views can inject their own navigation buttons.
Hope this can help you.
I know there are few answers on this topic. But none of them was working in my case.
I have a ListView with a style and an ItemContainerStyle. In the ItemContainer Style, I define some triggers in order to use a different DataTemplate depending if the item in the list is selected or not. Then, finally in the Datatemplate I have a context menu with a command. The problem is how to bind the command to the viewmodel.
This is the ListView:
<ListView
x:Name="lstPersons"
Grid.Row="1"
Style="{StaticResource ListViewStyle}"
ItemContainerStyle="{StaticResource ItemContainerStyle}"
DataContext="{Binding}"
ItemsSource="{Binding Path=Persons}"
Tag="{Binding}"
SelectedItem="{Binding Path=SelectedPerson, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
</ListView>
and these are the styles, datatemplates and contextmenu (defined in a resource dictionary).
The commands in the context menu do not work....:
<ContextMenu x:Key="SelectedItemContextMenu">
<MenuItem
Header="Do Something"
Command="{Binding Path=DataContext.DoSomethingCmd, ElementName=LayoutRoot}">
</MenuItem>
<MenuItem
Header="Do Something"
Command="{Binding PlacementTarget.Tag.DoSomethingCmd, RelativeSource={RelativeSource AncestorType=ContextMenu}}">
</MenuItem>
</ContextMenu>
<DataTemplate
x:Key="ItemTemplate">
<Canvas
Margin="4"
Width="60"
Height="60"
Background="LightGray">
<TextBlock
Foreground="Black"
Margin="2 0 0 0"
Opacity="0.5"
FontFamily="Segoe UI"
Text="{Binding Path=FirstName}" />
</Canvas>
</DataTemplate>
<DataTemplate
x:Key="ItemSelectedTemplate">
<Grid>
<Border
BorderBrush="Black"
BorderThickness="1"
Margin="3"
ContextMenu="{DynamicResource SelectedItemContextMenu}">
<Canvas
Width="60"
Height="60"
Background="LightBlue">
<TextBlock
Foreground="Black"
Margin="2 0 0 0"
Opacity="0.5"
FontFamily="Segoe UI"
Text="{Binding Path=FirstName}" />
</Canvas>
</Border>
</Grid>
</DataTemplate>
<!--style of the listviewitem-->
<Style
TargetType="{x:Type ListViewItem}"
x:Key="ItemContainerStyle">
<Setter
Property="ContentTemplate"
Value="{StaticResource ItemTemplate}" />
<Style.Triggers>
<Trigger
Property="IsSelected"
Value="True">
<Setter
Property="ContentTemplate"
Value="{StaticResource ItemSelectedTemplate}" />
</Trigger>
</Style.Triggers>
</Style>
<!--style of the listview-->
<Style
TargetType="{x:Type ListBox}"
x:Key="ListViewStyle">
<Setter
Property="Template">
<Setter.Value>
<ControlTemplate
TargetType="{x:Type ListBox}">
<Grid>
<Border>
<ScrollViewer
Focusable="false">
<WrapPanel
IsItemsHost="True"
Orientation="Horizontal"
Width="{Binding (FrameworkElement.ActualWidth), RelativeSource={RelativeSource AncestorType=ScrollContentPresenter}}"/>
</ScrollViewer>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Your ContextMenu is used inside a data template. I will be put in a different name scope of "LayoutRoot" and ElementName binding won't work. Also, the PlacementTarget of your context menu is the Border, and you've not setup any Tag on it. So the second command won't work either.
It looks like you are implement the commands on the ListBox level (or LayoutRoot?). It might be easier to put your context menu on the ListBox, and use ListBox.SelectedItem to find the current selection and apply your logic on it.
You can use RelativeSource:
<ContextMenu x:Key="SelectedItemContextMenu">
<MenuItem
Header="Do Something"
Command="{Binding Path=DataContext.DoSomethingCmd, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}">
</MenuItem>
</ContextMenu>
You should probably be using RoutedCommands instead of VM commands in this case. You would bind the RoutedCommand to the ContextMenu, and since you only need static object references for that, finding them shouldn't be a problem. Then you'd set up appropriate CommandBindings on the controls that should handle the commands (either ListView or ListViewItem, depending on whether you want the List-ViewModel or the Item-ViewModel to handle the command). These controls will know their ViewModels, so binding to them will not be a problem there. Through the process of Command Routing, which is built-in in WPF, the context menu will find the proper target for its command automatically.
For guidance on how to set up CommandBindings in a MVVM-friendly way, you might want to refer to http://wpfglue.wordpress.com/2012/05/07/commanding-binding-controls-to-methods/
I have a TabControl that allows users to manage documents such as the following:
At some point, I want to add a feature that allows users to float TabItems and dock them back into the TabControl much along the lines of what you can do in Visual Studio. This feature will allow users to more easily compare documents and copy/paste between them, etc.
I have some general ideas on how to go about doing this. The TabControl has its ItemsSource bound to a list of document view models.
To float the tab:
Add a Thumb control to the tab strip area of the TabItem.
When the user drags the Thumb, the associated document view model is removed from the TabControl list.
A separate document Window is brought up, bound with the document view model, to display/edit that document.
To dock the tab:
Add a DragOver event handler in the TabControl to recognise a document Window dragging over the tab strip area.
The associated document view model is added to the TabControl list.
The document Window is closed.
Are there any examples out there on how to do this, or do you have an approach to do this?
Thanks.
If you can't find or don't want to use a pre-existing control, I would highly recommend Bea Stollnitz's article about dragging and dropping between databound controls. You will probably have to alter it a bit to work with a DockPanel to identify what DockPanel.Dock the databound object should use, however I've found the code easy to alter in the past.
You would then setup two databound controls, such as a TabControl and a DockPanel, and when dragging/dropping between the two you are actually dragging/dropping the databound items between the ItemsSources.
I finally got around to implementing this feature, and I used AvalonDock 2.0, which is MVVM friendly. All I needed to do was to replace the TabControl with a DockingManager and modify a few Styles.
The DockingManager setup (I only have documents, not tools, etc.):
<avalonDock:DockingManager x:Name="tabDesigner" DocumentsSource="{Binding Items}">
<avalonDock:DockingManager.LayoutItemContainerStyle>
<Style TargetType="{x:Type avalonDockControls:LayoutItem}" BasedOn="{StaticResource DocumentItem}"/>
</avalonDock:DockingManager.LayoutItemContainerStyle>
<avalonDock:DockingManager.DocumentPaneControlStyle>
<Style TargetType="{x:Type avalonDockControls:LayoutDocumentPaneControl}" BasedOn="{StaticResource DocumentPane}"/>
</avalonDock:DockingManager.DocumentPaneControlStyle>
<avalonDockLayout:LayoutRoot>
<avalonDockLayout:LayoutPanel Orientation="Horizontal">
<avalonDockLayout:LayoutDocumentPane/>
</avalonDockLayout:LayoutPanel>
</avalonDockLayout:LayoutRoot>
</avalonDock:DockingManager>
I didn't need to use AvalonDock's template selectors, I was able to use the DataTemplates that were already set up for the previous TabControl.
I modified the LayoutItem, LayoutDocumentPaneControl, and LayoutDocumentTabItem Styles to do the extra binding to the view models and other layout differences (it took a little while to figure out how to bind to the view models that are within AvalonDock's model):
<Style x:Key="DocumentItem" TargetType="{x:Type avalonDockControls:LayoutItem}">
<Setter Property="Title" Value="{Binding Model.TabTitle}"/>
<Setter Property="CloseCommand" Value="{Binding Model.CloseConfirmCommand}"/>
<Setter Property="IsSelected" Value="{Binding Model.IsSelected, Mode=TwoWay}"/>
</Style>
<Style x:Key="DocumentPane" TargetType="{x:Type avalonDockControls:LayoutDocumentPaneControl}">
...
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type avalonDockControls:LayoutDocumentPaneControl}">
<Grid ClipToBounds="true" SnapsToDevicePixels="true" KeyboardNavigation.TabNavigation="Local">
...
<Grid Panel.ZIndex="1" Background="{DynamicResource TabControlHeaderBrush}" >
...
<avalonDockControls:DocumentPaneTabPanel x:Name="HeaderPanel" Grid.Column="0" IsItemsHost="true" Margin="4,0,16,0" Grid.Row="0" KeyboardNavigation.TabIndex="1"/>
<avalonDockControls:DropDownButton
...
Style="{DynamicResource ToolBarHorizontalOverflowButtonStyle}"
Grid.Column="1">
...
</avalonDockControls:DropDownButton>
</Grid>
<Border x:Name="ContentPanel"
...
CornerRadius="3">
<Border
...
>
<Border
...
>
<ContentPresenter x:Name="PART_SelectedContentHost"
ContentSource="SelectedContent"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
</Border>
</Border>
</Grid>
<ControlTemplate.Triggers>
...
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="{x:Type TabItem}">
...
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid>
<ContentPresenter
x:Name="Content"
ContentSource="Header"
...
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Setter.Value>
</Setter>
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<avalonDockControls:LayoutDocumentTabItem Model="{Binding}"/>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<avalonDockControls:LayoutDocumentControl Model="{Binding}"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type avalonDockControls:LayoutDocumentTabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type avalonDockControls:LayoutDocumentTabItem}">
<ControlTemplate.Resources>
...
</ControlTemplate.Resources>
<Grid x:Name="grid" Margin="8,1,8,0">
...
<Grid RenderTransformOrigin="0.5,0.5">
...
<StackPanel Orientation="Horizontal" Margin="3,0,2,0">
<ContentPresenter x:Name="TabContent" Content="{Binding Model, RelativeSource={RelativeSource TemplatedParent}}" TextBlock.Foreground="{DynamicResource UnselectedTabText}"
ContentTemplate="{Binding DocumentHeaderTemplate, Mode=OneWay, RelativeSource={RelativeSource AncestorType={x:Type avalonDock:DockingManager}, Mode=FindAncestor}}"
ContentTemplateSelector="{Binding DocumentHeaderTemplateSelector, Mode=OneWay, RelativeSource={RelativeSource AncestorType={x:Type avalonDock:DockingManager}, Mode=FindAncestor}}"
Margin="5,2,5,2"/>
<Button
x:Name="TabItemButton"
Command="{Binding Path=Model.Content.CloseConfirmCommand, RelativeSource={RelativeSource TemplatedParent}}"
Content="X"
...
/>
<StackPanel.ContextMenu>
<ContextMenu>
<MenuItem Header="{Binding Model.Content.CloseTabLabel, RelativeSource={RelativeSource TemplatedParent}}" Command="{Binding Model.Content.CloseTab, RelativeSource={RelativeSource TemplatedParent}}" ToolTip="{Binding Model.Content.CloseTabToolTipLabel, RelativeSource={RelativeSource TemplatedParent}}"></MenuItem>
<MenuItem Header="{Binding Model.Content.CloseOtherTabsLabel, RelativeSource={RelativeSource TemplatedParent}}" Command="{Binding Model.Content.CloseOtherTabs, RelativeSource={RelativeSource TemplatedParent}}" ToolTip="{Binding Model.Content.CloseOtherTabsToolTipLabel, RelativeSource={RelativeSource TemplatedParent}}"></MenuItem>
<MenuItem Header="{Binding Model.Content.NextTabLabel, RelativeSource={RelativeSource TemplatedParent}}" Command="{Binding Model.Content.NextTab, RelativeSource={RelativeSource TemplatedParent}}" ToolTip="{Binding Model.Content.NextTabToolTipLabel, RelativeSource={RelativeSource TemplatedParent}}"></MenuItem>
</ContextMenu>
</StackPanel.ContextMenu>
</StackPanel>
</Grid>
</Grid>
<ControlTemplate.Triggers>
...
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
This is an example of the end result:
I am trying to pass a listbox's Selected Index property as a command paramater to a context menu item, I have the command binding working (thanks to Will # ElementName Binding from MenuItem in ContextMenu) but I'm have trouble with my command paramater.
<UserControl>
<ListBox ItemsSource="{Binding myItems}">
<ListBox.Resources> <!-- The selected item is the item the mouse is over -->
<Style TargetType="ListBoxItem" BasedOn="{StaticResource {x:Type ListBoxItem}}">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsMouseOver,RelativeSource={RelativeSource Self}}"
Value="True">
<Setter Property="IsSelected" Value="True" />
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.Resources>
<ListBox.ItemTemplate>
<DataTemplate>
<Button Content="Edit" Grid.Column="4" Grid.Row="0" Tag="{Binding DataContext, ElementName=ProductBacklog}">
<Button.ContextMenu>
<ContextMenu>
<MenuItem Header="Remove"
Command="{Binding PlacementTarget.Tag.RemoveStoryClickCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}"
CommandParameter="{Binding <!--I NEED TO BIND TO THE LISTBOX-->, Path=SelectedIndex}"/>
</ContextMenu>
</Button.ContextMenu>
</Button>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</UserControl>
You can set the CommandParameter="{Binding }" to pass the current data item in that row to your Command
Edit
Just noticed your command is in a ContextMenu. ContextMenus are not part of WPF's default Visual Tree, so bindings do not work the same way. To bind to the current item, use the following:
<MenuItem Header="Remove"
Command="{Binding PlacementTarget.Tag.RemoveStoryClickCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}"
CommandParameter="{Binding PlacementTarget.DataContext,
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type ContextMenu}}}" />
This will bind to the DataContext of whatever control the ContextMenu is placed on, so in this case it will be Button.DataContext