I have a button with an Image as its content in a toolbar. I would like this button to open a menu beneath it when clicked. How?
<Toolbar>
<Button>
<Button.Content>
<Image Source="../Resources/help.png"></Image>
</Button.Content>
</Button>
</Toolbar>
Thanks!!
Instead of using a subclassed Button, you can use Attached Properties or a Behavior to implement the drop down button functionality, for a more WPF-like approach and so you don't impact the button style:
using System.Windows.Interactivity;
public class DropDownButtonBehavior : Behavior<Button>
{
private bool isContextMenuOpen;
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.AddHandler(Button.ClickEvent, new RoutedEventHandler(AssociatedObject_Click), true);
}
void AssociatedObject_Click(object sender, System.Windows.RoutedEventArgs e)
{
Button source = sender as Button;
if (source != null && source.ContextMenu != null)
{
if (!isContextMenuOpen)
{
// Add handler to detect when the ContextMenu closes
source.ContextMenu.AddHandler(ContextMenu.ClosedEvent, new RoutedEventHandler(ContextMenu_Closed), true);
// If there is a drop-down assigned to this button, then position and display it
source.ContextMenu.PlacementTarget = source;
source.ContextMenu.Placement = PlacementMode.Bottom;
source.ContextMenu.IsOpen = true;
isContextMenuOpen = true;
}
}
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.RemoveHandler(Button.ClickEvent, new RoutedEventHandler(AssociatedObject_Click));
}
void ContextMenu_Closed(object sender, RoutedEventArgs e)
{
isContextMenuOpen = false;
var contextMenu = sender as ContextMenu;
if (contextMenu != null)
{
contextMenu.RemoveHandler(ContextMenu.ClosedEvent, new RoutedEventHandler(ContextMenu_Closed));
}
}
}
Usage:
<!-- NOTE: xmlns:i="schemas.microsoft.com/expression/2010/interactivity" -->
<Button>
<i:Interaction.Behaviors>
<local:DropDownButtonBehavior/>
</i:Interaction.Behaviors>
<Button.Content>
<StackPanel Orientation="Horizontal">
<Image Source="/DropDownButtonExample;component/Assets/add.png" SnapsToDevicePixels="True" Height="16" Width="16" />
<TextBlock Text="Add"/>
<Separator Margin="2,0">
<Separator.LayoutTransform>
<TransformGroup>
<TransformGroup.Children>
<TransformCollection>
<RotateTransform Angle="90"/>
</TransformCollection>
</TransformGroup.Children>
</TransformGroup>
</Separator.LayoutTransform>
</Separator>
<Path Margin="2" VerticalAlignment="Center" Width="6" Fill="#FF527DB5" Stretch="Uniform" HorizontalAlignment="Right" Data="F1 M 301.14,-189.041L 311.57,-189.041L 306.355,-182.942L 301.14,-189.041 Z "/>
</StackPanel>
</Button.Content>
<Button.ContextMenu>
<ContextMenu>
<MenuItem Header="Attribute"/>
<MenuItem Header="Setting"/>
<Separator/>
<MenuItem Header="Property"/>
</ContextMenu>
</Button.ContextMenu>
</Button>
Current gist source and example here.
If you have the luxury of targeting .NET 4 or newer, the new Ribbon library has a RibbonMenuButton that can do this. In 4.5 it is as easy as referencing System.Windows.Controls.Ribbon in your project:
<RibbonMenuButton x:Name="ExampleMenu" SmallImageSource="/Images/Example.png">
<RibbonMenuItem x:Name="ExampleMenuItem" Header="Save" />
</RibbonMenuButton>
i found this two solutions after searching for it:
1) Split Button in WPF
2) DropDownButtons in WPF
the second solution is my favorit (source taken from the website by Andrew Wilkinson)
public class DropDownButton : ToggleButton
{
// *** Dependency Properties ***
public static readonly DependencyProperty DropDownProperty =
DependencyProperty.Register("DropDown",
typeof(ContextMenu),
typeof(DropDownButton),
new UIPropertyMetadata(null));
// *** Constructors ***
public DropDownButton() {
// Bind the ToogleButton.IsChecked property to the drop-down's IsOpen property
Binding binding = new Binding("DropDown.IsOpen");
binding.Source = this;
this.SetBinding(IsCheckedProperty, binding);
}
// *** Properties ***
public ContextMenu DropDown {
get { return (ContextMenu)this.GetValue(DropDownProperty); }
set { this.SetValue(DropDownProperty, value); }
}
// *** Overridden Methods ***
protected override void OnClick() {
if (this.DropDown != null) {
// If there is a drop-down assigned to this button, then position and display it
this.DropDown.PlacementTarget = this;
this.DropDown.Placement = PlacementMode.Bottom;
this.DropDown.IsOpen = true;
}
}
}
usage
<ctrl:DropDownButton Content="Drop-Down">
<ctrl:DropDownButton.DropDown>
<ContextMenu>
<MenuItem Header="Item 1" />
<MenuItem Header="Item 2" />
<MenuItem Header="Item 3" />
</ContextMenu>
</ctrl:DropDownButton.DropDown>
</ctrl:DropDownButton>
hope that helps you...
There are lots of ways to get this done and you might consider this approach...
<ToolBar DockPanel.Dock="Top">
<MenuItem IsSubmenuOpen="{Binding SomeProperty}">
<MenuItem.Header>
<Button Height="28">
<Button.Content>
<Image Source="---your image---"></Image>
</Button.Content>
</Button>
</MenuItem.Header>
<Menu>
<MenuItem Header="Do this" />
<MenuItem Header="Do that"/>
</Menu>
</MenuItem>
</ToolBar>
This wraps your button into a MenuItem that has a submenu. As shown here, the MenuItem property called IsSubMenuOpen is bound to a notifying property of type bool in your ViewModel called SomeProperty.
You would have to have your ViewModel toggle this property depending upon what you are actually trying to do. You may want to consider making your button a toggle button so as to facilitate closing the submenu, otherwise you'll have to wire up additional behaviour in your ViewModel.
Related
This is an example that highlights the problem:
<TextBlock Text="double click me" Width="150" Height="25"
ContextMenuOpening="TextBlock_ContextMenuOpening"
Mouse.MouseDown="TextBlock_MouseDown">
<TextBlock.ContextMenu>
<ContextMenu>
<MenuItem Header="test" />
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
When the context menu is open, I double click the TextBlock. The first hit of TextBlock_MouseDown has e.ClickCount = 1 as expected, but so does the second. Is there any way I can get the clicks to be part of the same chain?
The first click closes the ContextMenu so you should be able to handle the ContextMenuClosing and then compare the total time elapsed between when the ContextMenu was closed and when the TextBlock was clicked again, e.g.:
DateTime dt;
private void TextBlock_MouseDown(object sender, MouseButtonEventArgs e)
{
if (DateTime.Now.Subtract(dt).TotalSeconds <= 0.3)
{
MessageBox.Show("double click detected!");
dt = DateTime.MinValue;
}
}
private void TextBlock_ContextMenuClosing(object sender, ContextMenuEventArgs e)
{
dt = DateTime.Now;
}
<TextBlock Text="double click me" Width="150" Height="25"
ContextMenuClosing="TextBlock_ContextMenuClosing"
Mouse.MouseDown="TextBlock_MouseDown">
<TextBlock.ContextMenu>
<ContextMenu>
<MenuItem Header="test" />
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
How about using StaysOpenOnClick="True". You can close it after the double click:
<TextBlock Text="double click me" Width="150" Height="25" >
<TextBlock.ContextMenu>
<ContextMenu Name="cm">
<MenuItem PreviewMouseDoubleClick="MenuItem_PreviewMouseDoubleClick" Header="test"
StaysOpenOnClick="True" />
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
in code:
private void MenuItem_PreviewMouseDoubleClick(object sender, MouseButtonEventArgs e)
{
// ...
cm.IsOpen = false;
}
Also note that there is a StaysOpen property in ContextMenu too, and you can use it.
I am making a text editor program in WPF and I need to make a Plain button, which it's purpose is to remove the formatting (bold, italic, font such as Arial, font size) of text of the RichTextBox.
This is my code so far:
<Window x:Class="TextEditor.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TextEditor"
Title="Text Editor" Height="480" Width="640">
<DockPanel>
<Menu DockPanel.Dock="Top">
<MenuItem Header="_File" Name="Menu">
<MenuItem Header="New" Name="New"
Click="New_Click" />
<MenuItem Header="Save" Name="Save"
Click="Save_Click" />
</MenuItem>
</Menu>
<DockPanel DockPanel.Dock="Top">
<ToolBar>
<ToggleButton x:Name="boldButton"
ToolTip="Bold"
Command="{x:Static EditingCommands.ToggleBold}" CommandTarget="{Binding ElementName=_richTextBox}">
<Image Source="Icons/text_bold.png"
Height="25"
Width="25"/>
</ToggleButton>
<ToggleButton x:Name="italicButton"
ToolTip="Italic"
Command="{x:Static EditingCommands.ToggleItalic}" CommandTarget="{Binding ElementName=_richTextBox}">
<Image Source="Icons/text_italic.png"
Height="25"
Width="25"/>
</ToggleButton>
<ToggleButton x:Name="PlainButton"
ToolTip="Make the text plain"
Click="PlainButton_Click">
PlainText
</ToggleButton>
<Button x:Name="BackgroundButton"
ToolTip="Change the background of the textbox"
Click="BackgroundButton_Click">
Change the background
</Button>
<Separator/>
<ComboBox x:Name="fonts"
MinWidth="100"
DataContext="{x:Static Fonts.SystemFontFamilies}"
ItemsSource="{Binding}"
ToolTip="Font"
SelectionChanged="Font_SelectionChanged"/>
<ComboBox x:Name="fontSize"
MinWidth="40"
ToolTip="Font Size"
>
</ComboBox>
</ToolBar>
</DockPanel>
<StatusBar DockPanel.Dock="Bottom">
<TextBlock x:Name="status"/>
</StatusBar>
<RichTextBox x:Name="body"
FontSize="{Binding ElementName=fontSize, Path=SelectedItem}"
SpellCheck.IsEnabled="True"
AcceptsReturn="True"
AcceptsTab="True"
SelectionChanged="body_SelectionChanged"
BorderThickness="0 2 0 0"/>
</DockPanel>
</Window>
C sharp code:
public MainWindow()
{
InitializeComponent();
for (double i = 8; i <= 48; i += 2)
{
fontSize.Items.Add(i);
}
}
private void body_SelectionChanged(object sender, RoutedEventArgs e)
{
object temp = body.Selection.GetPropertyValue(Inline.FontFamilyProperty);
fonts.SelectedItem = temp;
}
private void New_Click(object sender, RoutedEventArgs e)
{
body.Document.Blocks.Clear();
}
private void Save_Click(object sender, RoutedEventArgs e)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = "Text file|*.txt";
sfd.FileName = "Untitled document";
if (sfd.ShowDialog() == true)
{
FileStream fileStream = new FileStream(sfd.FileName, FileMode.Create);
TextRange range = new TextRange(body.Document.ContentStart, body.Document.ContentEnd);
range.Save(fileStream, DataFormats.Text);
}
}
private void Font_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (fonts.SelectedItem != null)
body.Selection.ApplyPropertyValue(Inline.FontFamilyProperty, fonts.SelectedItem);
}
private void PlainButton_Click(object sender, RoutedEventArgs e)
{
//the code of the plain button
}
private void BackgroundButton_Click(object sender, RoutedEventArgs e)
{
body.Background = Brushes.Yellow;
}
It's a solution from 2009 ... I don't know if the richtext API in .NET has improved, but this post seems to have a solution for what you need.
Use the following code for WPF, if you are still looking for answers.
myRichTextBox.SelectAll();
myRichTextBox.Selection.ClearAllProperties();
I am showing a UserControl inside ContextMenu. Futhermore in that UserControl I am showing a Popup which contains some buttons and datagrid. All the data in Popup loads during runtime.
The problem is ContextMenu ignores the property StaysOpen even though it is set to true.
The Popup does stay open when I set StaysOpen to true in code behind but ContextMenu doesn't.
I tried it with following code:
<UserControl x:Class="UserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<Popup Name="popupState" PlacementTarget="{Binding ElementName=txtSearch}" PopupAnimation="Slide" Placement="Bottom" Focusable="True" AllowsTransparency="True" VerticalAlignment="Top">
<Button HorizontalAlignment="Right" Margin="5" Background="GhostWhite" Name="btnSelectAll" Click="btnSelectAll_Click" Width="30" Height="30">
<my:DataGrid VerticalAlignment="Stretch" MaxHeight="300" VerticalScrollBarVisibility="Auto" RowHeaderWidth="0" Margin="5,5,5,1" Background="White" HorizontalAlignment="Stretch" Name="DGTeamCommunicator" HorizontalContentAlignment="Left" HorizontalGridLinesBrush="#D6D7D6" GridLinesVisibility="None">
<my:DataGridTemplateColumn Width="Auto" MinWidth="30">
<my:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" ContextMenuService.IsEnabled="True" ContextMenuService.HasDropShadow="True">
<Button Name="btnCall" Click="btnCall_Click" ContextMenuService.IsEnabled="True">
</Button>
</StackPanel>
</DataTemplate>
</my:DataGridTemplateColumn.CellTemplate>
</my:DataGridTemplateColumn>
</my:DataGrid>
</Popup>
My requirement is to Prevent the Popup as well as ContextMenu from closing when the buttons in Popup is clicked.
Kindly provide me a solution for this.
The bad news is that this behavior is by design. ContextMenu is defined to display few menus and when one of them is being clicked the ContextMenu internally sets the IsOpen to false.
The good news is that behavior should stay so and for any other customization you should take a Popup instead of ContextMenu. BUT if you MUST use ContextMenu for whatever reason here is a workaround:
<StackPanel>
<Button>
Popup Demo
<Button.ContextMenu>
<local:StaysOpenContextMenu x:Name="ContextMenu1" StaysOpen="True">
<StackPanel>
<TextBox x:Name="TextBox1" Width="100" TextChanged="OnTextChanged"/>
<Popup x:Name="Popup1" Placement="Bottom" PlacementTarget="{Binding ElementName=tbx}" StaysOpen="True">
<Button Content="click me"/>
</Popup>
</StackPanel>
</local:StaysOpenContextMenu>
</Button.ContextMenu>
</Button>
<Button Click="OnClick">Close Popup</Button>
</StackPanel>
You will need a custom ContextMenu to get the job done:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void OnTextChanged(object sender, TextChangedEventArgs e)
{
this.Popup1.IsOpen = true;
}
private void OnClick(object sender, RoutedEventArgs e)
{
this.Popup1.IsOpen = false;
this.ContextMenu1.CloseContextMenu();
}
}
public class StaysOpenContextMenu : ContextMenu
{
private bool mustStayOpen;
static StaysOpenContextMenu()
{
IsOpenProperty.OverrideMetadata(
typeof(StaysOpenContextMenu),
new FrameworkPropertyMetadata(false, null, CoerceIsOpen));
StaysOpenProperty.OverrideMetadata(
typeof(StaysOpenContextMenu),
new FrameworkPropertyMetadata(false, PropertyChanged, CoerceStaysOpen));
}
private static void PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
StaysOpenContextMenu menu = (StaysOpenContextMenu)d;
menu.mustStayOpen = (bool)e.NewValue;
}
private static object CoerceStaysOpen(DependencyObject d, object basevalue)
{
d.CoerceValue(IsOpenProperty);
return basevalue;
}
private static object CoerceIsOpen(DependencyObject d, object basevalue)
{
StaysOpenContextMenu menu = (StaysOpenContextMenu)d;
if (menu.StaysOpen && menu.mustStayOpen)
{
return true;
}
return basevalue;
}
public void CloseContextMenu()
{
this.mustStayOpen = false;
this.IsOpen = false;
}
}
I have a prism delegate command setup for refresh the data in my application.
I also have setup shortcuts for close and about window using delegate command.
Using F5 also does not trigger the refresh in the view model. If I use Alt+F4, the application closes. But it does not execute the CloseApplication method in the view model. What is missing in the following code to execute the ViewModel using the Gesture Shorcuts?
UserControl:
<UserControl.InputBindings>
<KeyBinding Gesture="ALT+F4" Command="{Binding CloseCommand}" />
<KeyBinding Gesture="F5" Command="{Binding RefreshCommand}" />
</UserControl.InputBindings>
<DockPanel>
<Menu DockPanel.Dock="Top">
<MenuItem Header="_File">
<MenuItem Header="E_xit" Command="{Binding CloseCommand}" InputGestureText="Alt+F4" />
<MenuItem Header="Refresh" Command="{Binding RefreshCommand}" InputGestureText="F5" />
</MenuItem>
<MenuItem Header="_Help">
<MenuItem Header="_About" Command="{Binding AboutCommand}" />
</MenuItem>
</Menu>
<ToolBar ToolBarTray.IsLocked="True">
<Button Content="Home" MinHeight="50" MinWidth="80" VerticalContentAlignment="Bottom" />
<Button Content="Page 1" MinHeight="50" MinWidth="80" VerticalContentAlignment="Bottom" />
<Button Content="Page 2" MinHeight="50" MinWidth="80" VerticalContentAlignment="Bottom" />
</ToolBar>
</DockPanel>
ViewModel of the UserControl
public class TopMenuViewModel:NotificationObject
{
private DelegateCommand _closeCommand;
private DelegateCommand _aboutCommand;
private DelegateCommand _refreshCommand;
public TopMenuViewModel()
{
_closeCommand = new DelegateCommand(CloseApplication);
_aboutCommand = new DelegateCommand(ShowAboutWindow);
_refreshCommand = new DelegateCommand(RefreshApplication);
}
private void ShowAboutWindow()
{
Console.WriteLine("Show about window");
}
private void CloseApplication()
{
Application.Current.Shutdown();
}
private void RefreshApplication()
{
Console.WriteLine("Refreshing..");
}
public ICommand CloseCommand
{
get { return _closeCommand; }
}
public ICommand AboutCommand
{
get { return _aboutCommand; }
}
public ICommand RefreshCommand
{
get { return _refreshCommand; }
}
}
The view model methods are called if I use the mouse to click the menu or use the Alt+x or Alt+A. But not using the KeyBinding that I have put in. Thanks for your help.
I have a WPF application..In which I have an Image control in Xaml file.
On right click of this image I have a context menu.
I would like to have same to be displayed on "Left click" also.
How do I do this in MVVM way ?
Here is a XAML only solution.
Just add this style to your button.
This will cause the context menu to open on both left and right click. Enjoy!
<Button Content="Open Context Menu">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Style.Triggers>
<EventTrigger RoutedEvent="Click">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="ContextMenu.IsOpen">
<DiscreteBooleanKeyFrame KeyTime="0:0:0" Value="True"/>
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu>
<MenuItem />
<MenuItem />
</ContextMenu>
</Setter.Value>
</Setter>
</Style>
</Button.Style>
</Button>
You can do this by using the MouseDown event of an Image like this
<Image ... MouseDown="Image_MouseDown">
<Image.ContextMenu>
<ContextMenu>
<MenuItem .../>
<MenuItem .../>
</ContextMenu>
</Image.ContextMenu>
</Image>
And then show the ContextMenu in the EventHandler in code behind
private void Image_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left)
{
Image image = sender as Image;
ContextMenu contextMenu = image.ContextMenu;
contextMenu.PlacementTarget = image;
contextMenu.IsOpen = true;
e.Handled = true;
}
}
You can invent your own DependencyProperty which opens a context menu when image is clicked, just like this:
<Image Source="..." local:ClickOpensContextMenuBehavior.Enabled="True">
<Image.ContextMenu>...
</Image.ContextMenu>
</Image>
And here is a C# code for that property:
public class ClickOpensContextMenuBehavior
{
private static readonly DependencyProperty ClickOpensContextMenuProperty =
DependencyProperty.RegisterAttached(
"Enabled", typeof(bool), typeof(ClickOpensContextMenuBehavior),
new PropertyMetadata(new PropertyChangedCallback(HandlePropertyChanged))
);
public static bool GetEnabled(DependencyObject obj)
{
return (bool)obj.GetValue(ClickOpensContextMenuProperty);
}
public static void SetEnabled(DependencyObject obj, bool value)
{
obj.SetValue(ClickOpensContextMenuProperty, value);
}
private static void HandlePropertyChanged(
DependencyObject obj, DependencyPropertyChangedEventArgs args)
{
if (obj is Image) {
var image = obj as Image;
image.MouseLeftButtonDown -= ExecuteMouseDown;
image.MouseLeftButtonDown += ExecuteMouseDown;
}
if (obj is Hyperlink) {
var hyperlink = obj as Hyperlink;
hyperlink.Click -= ExecuteClick;
hyperlink.Click += ExecuteClick;
}
}
private static void ExecuteMouseDown(object sender, MouseEventArgs args)
{
DependencyObject obj = sender as DependencyObject;
bool enabled = (bool)obj.GetValue(ClickOpensContextMenuProperty);
if (enabled) {
if (sender is Image) {
var image = (Image)sender;
if (image.ContextMenu != null)
image.ContextMenu.IsOpen = true;
}
}
}
private static void ExecuteClick(object sender, RoutedEventArgs args)
{
DependencyObject obj = sender as DependencyObject;
bool enabled = (bool)obj.GetValue(ClickOpensContextMenuProperty);
if (enabled) {
if (sender is Hyperlink) {
var hyperlink = (Hyperlink)sender;
if(hyperlink.ContextMenu != null)
hyperlink.ContextMenu.IsOpen = true;
}
}
}
}
If you want to do this just in Xaml without using code-behind you can use Expression Blend's triggers support:
...
xmlns:i="schemas.microsoft.com/expression/2010/interactivity"
...
<Button x:Name="addButton">
<Button.ContextMenu>
<ContextMenu ItemsSource="{Binding Items}" />
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ei:ChangePropertyAction TargetObject="{Binding ContextMenu, ElementName=addButton}" PropertyName="PlacementTarget" Value="{Binding ElementName=addButton, Mode=OneWay}"/>
<ei:ChangePropertyAction TargetObject="{Binding ContextMenu, ElementName=addButton}" PropertyName="IsOpen" Value="True"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button.ContextMenu>
</Button>
you only need add the code into function Image_MouseDown
e.Handled = true;
Then it will not disappear.
Hey I came across the same problem looking for a solution which I didn't find here.
I don't know anything about MVVM so it's probably not MVVM conform but it worked for me.
Step 1: Give your context menu a name.
<Button.ContextMenu>
<ContextMenu Name="cmTabs"/>
</Button.ContextMenu>
Step 2: Double click the control object and insert this code. Order matters!
Private Sub Button_Click_1(sender As Object, e As Windows.RoutedEventArgs)
cmTabs.StaysOpen = True
cmTabs.IsOpen = True
End Sub
Step 3: Enjoy
This will react for left & right click. It's a button with a ImageBrush with a ControlTemplate.
you can bind the Isopen Property of the contextMenu to a property in your viewModel like "IsContextMenuOpen".
but the problem is your can't bind directly the contextmenu to your viewModel because it's not a part of your userControl hiarchy.So to resolve this you should bing the tag property to the dataontext of your view.
<Image Tag="{Binding DataContext, ElementName=YourUserControlName}">
<ContextMenu IsOpen="{Binding PlacementTarget.Tag.IsContextMenuOpen,Mode=OneWay}" >
.....
</ContextMenu>
<Image>
Good luck.
Interactivity is old and not support any more. The new approach for the implementation is:
xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
<Button x:Name="ConvertVideoButton">
<Button.ContextMenu>
<ContextMenu VerticalContentAlignment="Top" >
<MenuItem Header="Convert 1" Command="{Binding ConvertMkvCommand}" />
<MenuItem Header="Convert 2" Command="{Binding ConvertMkvCommand}" />
</ContextMenu>
</Button.ContextMenu>
<b:Interaction.Triggers>
<b:EventTrigger EventName="Click">
<b:ChangePropertyAction TargetObject="{Binding ContextMenu, ElementName=ConvertVideoButton}" PropertyName="PlacementTarget" Value="{Binding ElementName=ConvertVideoButton, Mode=OneWay}"/>
<b:ChangePropertyAction TargetObject="{Binding ContextMenu, ElementName=ConvertVideoButton}" PropertyName="IsOpen" Value="True"/>
</b:EventTrigger>
</b:Interaction.Triggers>
</Button>
XAML
<Button x:Name="b" Content="button" Click="b_Click" >
<Button.ContextMenu >
<ContextMenu >
<MenuItem Header="Open" Command="{Binding OnOpen}" ></MenuItem>
<MenuItem Header="Close" Command="{Binding OnClose}"></MenuItem>
</ContextMenu>
</Button.ContextMenu>
</Button>
C#
private void be_Click(object sender, RoutedEventArgs e)
{
b.ContextMenu.DataContext = b.DataContext;
b.ContextMenu.IsOpen = true;
}