Popup not working on MenuItem - c#

I have to display a Popup on click of a MenuItem. I have written the below code for that:
<ContextMenu>
<Border>
<MenuItem Name="ack" Header="ACK" HorizontalAlignment="Center" Command="{Binding AcknowledgeCommand}" Visibility="{Binding IsAcked, Converter={StaticResource showOnFalse}}" Click="MenuItem_Click_1"/>
</Border>
<Separator/>
<Border>
<MenuItem Header="Info" HorizontalAlignment="Center" Click="MenuItem_Click"/>
</Border>
<Separator/>
<Border>
<MenuItem Header="Goto" HorizontalAlignment="Center"/>
</Border>
<Popup Name="infoPopup" Placement="Mouse" HorizontalOffset="-100" VerticalOffset="-100" AllowsTransparency="True" StaysOpen="True">
<Alarms:UserControl_MYUC DataContext="{Binding TopMost}" Background="{DynamicResource DetailPanelCompartmentTitleBg}" BorderBrush="{DynamicResource SecWindowBtnBorder}"/>
</Popup>
</ContextMenu>
OnClick of the MenuItem, I have written the following code:
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
infoPopup.Visibility = System.Windows.Visibility.Visible;
infoPopup.IsOpen = true;
}
I am able to see the popup on click of the Info button, but the Popup goes within a second. I want it to be visible till the user clicks some other area or the popup loses focus.
Please suggest what to do.

Apply StaysOpenOnClick="True" to your MenuItem.

Please use the StaysOpen Boolean to define what you wanted.
myPopup.StaysOpen = true;
For further information, please refer to the following link : https://msdn.microsoft.com/en-us/library/system.windows.controls.primitives.popup.staysopen(v=vs.110).aspx

Related

WPF sending mouse wheel event from ContextMenu to Window

I have a window, on it, i have a button. The button has a context menu:
<Window>
<ScrollViewer Height="500">
<Button Height = "2000">
<Button.ContextMenu>
<ContextMenu>
<MenuItem Header="Item1"></MenuItem>
<MenuItem Header="Item2"></MenuItem>
<MenuItem Header="Item3"></MenuItem>
</ContextMenu>
</Button.ContextMenu>
</Button>
</ScrollViewer>
</Window>
Whenever i right click on button, the context menu will be shown. When i move the mouse out of the context menu and scroll the wheel, the scrollViewer doesn't scroll at all. I have tried many ways on mouse leave or mouse enter events but nothing helps. I want the context menu is still showing but the wheel event is sent to the scrollViewer (or window), if i click outside of the contextmenu, it will close normally.
In win-form application, i have the same issue but i can solve it by using ContextMenuStrip as a replacement for ContextMenu. In WPF, looks like no ContextMenuStrip.
Unfortunately, context menu popups are not ancestors to their hosts when it comes to the WPF logical tree. This means that event bubbling doesn't work from context menu to the scrollviewer, so the scrollviewer won't be informed of any mouse wheel activity.
However, if you just want scrolling up/down in a scrollviewer to work, you can replicate the behavior yourself pretty easily by listening to the MouseWheel event on the context menu and then scrolling the ScrollViewer manually.
eg. the xaml:
<ScrollViewer Height="500" x:Name="MyScrollViewer">
<Button Height = "2000">
<Button.ContextMenu>
<ContextMenu x:Name="MyContextMenu">
<MenuItem Header="Item1"></MenuItem>
<MenuItem Header="Item2"></MenuItem>
<MenuItem Header="Item3"></MenuItem>
</ContextMenu>
</Button.ContextMenu>
</Button>
</ScrollViewer>
In the codebehind for your view you could do something similar to the following:
public MainWindow()
{
InitializeComponent();
this.MyContextMenu.MouseWheel += OnContextMenuMouseWheel;
}
private void OnContextMenuMouseWheel(object sender, MouseWheelEventArgs e)
{
var currentOffset = MyScrollViewer.VerticalOffset;
var newOffset = currentOffset - e.Delta;
MyScrollViewer.ScrollToVerticalOffset(newOffset);
e.Handled = true;
}
Instread of using a ContextMenu, you could use a Popup that looks like a ContextMenu:
<ScrollViewer Height="500">
<Button Height="2000">
<Popup x:Name="popup" Placement="Mouse" StaysOpen="False"
xmlns:theme="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero2">
<theme:SystemDropShadowChrome Name="Shdw" Color="Transparent" SnapsToDevicePixels="true">
<Border Name="ContextMenuBorder" Background="#F5F5F5" BorderBrush="#FF959595" BorderThickness="1" SnapsToDevicePixels="True">
<ScrollViewer Name="ContextMenuScrollViewer" Grid.ColumnSpan="2" Margin="1,0"
Style="{DynamicResource {ComponentResourceKey TypeInTargetAssembly={x:Type FrameworkElement}, ResourceId=MenuScrollViewer}}">
<Grid RenderOptions.ClearTypeHint="Enabled">
<Canvas Height="0" Width="0" HorizontalAlignment="Left" VerticalAlignment="Top">
<Rectangle Name="OpaqueRect" Height="{Binding ElementName=ContextMenuBorder, Path=ActualHeight}"
Width="{Binding ElementName=ContextMenuBorder, Path=ActualWidth}"
Fill="{Binding ElementName=ContextMenuBorder, Path=Background}"
SnapsToDevicePixels="True"/>
</Canvas>
<Rectangle Fill="#F1F1F1" HorizontalAlignment="Left" Width="28" Margin="1,2" RadiusX="2" RadiusY="2" SnapsToDevicePixels="True"/>
<Rectangle HorizontalAlignment="Left" Width="1" Margin="29,2,0,2" Fill="#E2E3E3" SnapsToDevicePixels="True"/>
<Rectangle HorizontalAlignment="Left" Width="1" Margin="30,2,0,2" Fill="White" SnapsToDevicePixels="True"/>
<StackPanel>
<MenuItem Header="Item1"></MenuItem>
<MenuItem Header="Item2"></MenuItem>
<MenuItem Header="Item3"></MenuItem>
</StackPanel>
</Grid>
</ScrollViewer>
</Border>
</theme:SystemDropShadowChrome>
</Popup>
<Button.Triggers>
<EventTrigger RoutedEvent="MouseRightButtonUp">
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetName="popup" Storyboard.TargetProperty="IsOpen">
<DiscreteBooleanKeyFrame KeyTime="00:00:00.1" Value="True"/>
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</ScrollViewer>
Remember to add a reference to PresentationFramework.Aero2.dll if you want to use SystemDropShadowChrome.

C# MVVM: MenuItem Command don´t execute in ViewModel

I created a Delete MenuItem and binding a command to it.
Now I have the problem, if I am pressing the Delete MenuItem, nothing happens. Also if the program is executed with the debugger, it never reaches the private void DeleteItem.
xaml:
<ListBox.ItemTemplate>
<DataTemplate>
<Border Background="#F5F5F5" Width="80" Height="60" Margin="0,5,5,5">
<Border.ContextMenu>
<ContextMenu>
<MenuItem Header="Delete"
Command="{Binding Path=DeleteItemCommand, RelativeSource={RelativeSource FindAncestor, AncestorType= MenuItem}}">
<MenuItem.Icon>
<Label FontFamily="#FontAwesome" Content="" />
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</Border.ContextMenu>
ViewModel:
public ICommand DeleteItemCommand { get; set; }
DeleteItemCommand = new RelayCommand(DeleteItem);
private void DeleteItem(object obj)
{
try
{
// Do Magic
}
catch (Exception)
{
MessageBox.Show(error);
}
}
Would be great, if someone could help me or have any ideas how to solve it, because i can´t find the error.
ContextMenu is indeed not part of the visual tree. But I think because of that reason RelativeSource will not work because the binding will look up to the visual tree for the datacontext. contextMenu is not part of that visual tree so it will not find the proper datacontext. I've found a solution for this in the past using a proxy element in the resources for the window. Then set this proxyelement as content for a hidden contentcontrol in the window. On the menuItem set the CommandBinding to Datacontext.DeleteCommand and the soure to the static resource proxyelement. It is a bit hackish, but it works.
So to show some xaml, try this:
First in the resources of the window create a frameworkelement with the datacontext set to the windows datacontext (the viewmodel)
<Window.Resources>
<FrameworkElement x:Key="ProxyElement" DataContext="{Binding}"/>
</Window.Resources>
Then use the resource for the content of a collapsed content control. And set the proper binding to the menuItem. Something like this:
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ContentControl Visibility="Collapsed" Content="{StaticResource ProxyElement}"/>
<ListBox x:Name="lbTest" Grid.Row="1">
<ListBox.ItemTemplate>
<DataTemplate>
<Border Background="#F5F5F5" Width="80" Height="60" Margin="0,5,5,5">
<Border.ContextMenu>
<ContextMenu>
<MenuItem Header="Delete"
Command="{Binding DataContext.DeleteCommand, Source={StaticResource ProxyElement}}">
<MenuItem.Icon>
<Label FontFamily="#FontAwesome" Content="" />
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</Border.ContextMenu>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
This should work. Give it a try.
Not sure if this will help but try using Binding instead of Binding Path.
ContextMenu is not part of VisualTree, that's why the binding fails. You can use some kind of relay like ContextMenu.PlacementTarget.Tag.Property as a cache for the second trail of binding search.
<ContextMenu>
<MenuItem Command="my:ImgTreeView.Folders" Header="Folders"
IsEnabled="{Binding Path=PlacementTarget.Tag.IsCheckFolder, RelativeSource={RelativeSource AncestorType=ContextMenu}}">
<MenuItem.Icon>
<Image Source="StarFolders.png" />
</MenuItem.Icon>
</MenuItem>
<!-- ... -->
</ContextMenu>

How to hide listview when clicked, and reroute to another page?

I'm currently creating a menu with a ListView and ListViewItems. In the menu, I want to go back from one page to a predefined page. The ListviewItem, which were clicked, should disappear when it takes me back to the predefined page. However, I'm stuck at how the flow between the views is handled and how to hide the ListView when it is clicked.
XAML
<ListView x:Name="GoBackMenu" Foreground="#FF5C99D6" ScrollViewer.HorizontalScrollBarVisibility="Disabled" SelectionChanged="ListViewMenu_ClashPressed" SelectedIndex="{Binding SelectedIndex}" Margin="0 0 0 290" Visibility="visible" >
<ListViewItem x:Name="Swift_goBackView" Height="80">
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon Kind="Backburger" Height="25" Width="25" Margin="10"/>
<TextBlock Text="Back to overview" VerticalAlignment="Center" Margin="20 10"/>
</StackPanel>
</ListViewItem>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<EventSetter Event="PreviewMouseLeftButtonDown" Handler="ListViewItem_PreviewMouseLeftButtonDown" ></EventSetter>
</Style>
</ListView.ItemContainerStyle></ListView>
Thanks for the help in advance.
You could remove the clicked item like this in your event handler:
private void ListViewItem_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
ListViewItem lvi = (ListViewItem)sender;
GoBackMenu.Items.Remove(lvi);
}
How the "the flow between the views is handled" depends on your current navigation implementation which you haven't described.

Enable/Disable Textblock in a ContextMenu

I have a ContextMenu with a MenuItem inside it. The MenuItem is a TextBlock as shown in the below code:
<ContextMenu>
<Border>
<MenuItem>
<MenuItem.Header>
<TextBlock Text="ACK" HorizontalAlignment="Right"/>
</MenuItem.Header>
</MenuItem>
</Border>
</ContextMenu>
How do I enable or disable it at runtime. If I click it once, it should be disabled.
PS: I don't want to write code-behind for this. I need to achieve it from the XAML as this is done in a UserControl and is going to be used in many applications.

TextBox Customization Malfunction

I needed to create a textBoox that completely blends with the background so I used this XAML:
<TextBox Text="Hello" VerticalAlignment="Bottom" Name="txtAsk" FontFamily="Consolas" Margin="8,0,0,0" TextWrapping="Wrap" AutoWordSelection="True" KeyDown="onEnter">
<TextBox.Template>
<ControlTemplate TargetType="{x:Type TextBox}">
<Grid>
<Rectangle Stroke="{StaticResource ResourceKey=detailMarkBrush}" StrokeThickness="0"/>
<TextBox Margin="4" Text="{TemplateBinding Text}" BorderThickness="0" Background="{x:Null}" SnapsToDevicePixels="True" />
</Grid>
</ControlTemplate>
</TextBox.Template>
</TextBox>
However, now the problem is, when I attached a button to the interface and triggered it to show the content of the TextBox in a message window, it only shows the default text even after changing the value inside the text box!
The button code is as follows:
private void btnTriggerEnter_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show(txtAsk.Text);
}
I am not sure where I screwed up. Please comment if any other detail is required.
My MainWindow has this code:
public MainWindow()
{
InitializeComponent();
Loaded += new RoutedEventHandler(MainWindow_Loaded);
}
Thanks.
You should use:
Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Text}"
That's because TemplateBinding only gives you a OneWay source (in the underlying Binding), you need TwoWay.
http://blogs.msdn.com/b/liviuc/archive/2009/12/14/wpf-templatebinding-vs-relativesource-templatedparent.aspx
WPF TemplateBinding vs RelativeSource TemplatedParent

Categories