How to hide menu item of AttachedFlyout menu? - c#

I am able to display a right clicked menu using the below code programmatically, showing/hiding required menu-items is easy, since we can create MenuFlyoutItem as we wish.
private void MyGrid_RightTapped(object sender, RightTappedRoutedEventArgs e)
{
MenuFlyout myFlyout = new MenuFlyout();
MenuFlyoutItem mnu1 = new MenuFlyoutItem { Text = "Rename" };
MenuFlyoutItem mnu2 = new MenuFlyoutItem { Text = "Delete" };
myFlyout.Items.Add(mnu1);
myFlyout.Items.Add(mnu2);
mnu1.Click += mnu1_Click;
mnu2.Click += mnu2_Click;
FrameworkElement senderElement = sender as FrameworkElement;
myFlyout.ShowAt(sender as UIElement, e.GetPosition(sender as UIElement));
}
But, When I create menu using xaml as AttachedFlyout, I am unable to hide a particular menu item. here is my code:
<ListView.ItemTemplate>
<DataTemplate >
..............
<Grid Name="GrdForFolderMenu">
<FlyoutBase.AttachedFlyout >
<MenuFlyout Placement="Right">
<MenuFlyoutItem Name="MenuFolderCreate" Text="New Folder" Click="MenuFolderCreate_Click" DataContext="Folders"/>
<MenuFlyoutItem Name="MenuFolderRename" Text="Rename" Click="MenuFolderRename_Click"/>
<MenuFlyoutItem Name="MenuFolderExport" Text="Export" Click="MenuFolderExport_Click" />
<MenuFlyoutSeparator />
<MenuFlyoutItem Name="MenuFolderDelete" Text="Delete" Click="MenuFolderDelete_Click" />
</MenuFlyout>
</FlyoutBase.AttachedFlyout>
......
........
Here is my right click event:
private void myListView_RightTapped(object sender, RightTappedRoutedEventArgs e)
{
FlyoutBase.ShowAttachedFlyout((FrameworkElement)sender);
}
Struggling for a long to hide particular menu item, in code! Please help!

You just need to get the MenuFlyout and either set the Visibility of the specific MenuFlyoutItem to Collapsed or remove it from the list.
if (FlyoutBase.GetAttachedFlyout((FrameworkElement)sender) is MenuFlyout menuFlyout)
{
// Hide 'MenuFolderExport' MenuFlyoutItem
//menuFlyout.Items[2].Visibility = Visibility.Collapsed;
// Or, remove 'MenuFolderExport' MenuFlyoutItem
menuFlyout.Items.Remove(menuFlyout.Items[2]);
}
FlyoutBase.ShowAttachedFlyout((FrameworkElement)sender);
I'd also attach the RightTapped to your GrdForFolderMenu and replace all Name="xxx" with x:Name="xxx".

Related

Enable one-click instead of double-click when clicking NavigationViewPaneDisplayMode

Introduction
I want to make the header button to be used to minimize items with a one click action, not double one
Screenshot of the header button
Source Code
StackPanel stackPanel = new StackPanel();
InitializeComponent();
NavigationView navigationView = new NavigationView();
navigationView.PaneDisplayMode = NavigationViewPaneDisplayMode.LeftMinimal;
navigationView.IsPaneOpen = false;
NavigationViewItem navigationViewItem = new NavigationViewItem();
void NavigationView(object sender, TappedRoutedEventArgs e)
{
navigationView.IsPaneOpen = true;
}
navigationViewItem.Icon = new SymbolIcon(Symbol.Admin);
navigationViewItem.Content = "Test";
navigationView.MenuItems.Add(navigationViewItem);
stackPanel.Children.Add(navigationView);
Content = stackPanel;
Problem
I want to run the code when the header button
clicked once, not twice, but I don't know how to change the source code to do that.
By testing, when clicking the header button, items are minimized. The default operation is once click. It works well.
In addition, why did you create UI through code behind? I suggest you could create it through xaml code.
For example:
<StackPanel>
<NavigationView PaneDisplayMode="LeftMinimal" IsPaneOpen="True">
<NavigationView.MenuItems >
<NavigationViewItem Content="Test" Icon="Admin" />
</NavigationView.MenuItems>
</NavigationView>
</StackPanel>

How to create a ContextMenu when the mouse button is pressed

I made a code for a DataGrid that fire the right mouse button event, in particular:
private void Squadre_DataGrid_MouseClick(object sender, MouseEventArgs e)
{
if (e.RightButton == MouseButtonState.Pressed)
{
//Context menu
}
}
I want create a ContextMenu inside the condition, and associate for each item of the ContextMenu a method that will be executed if the item will be choose.
How to do this?
Perhaps you can achieve that in XAML. Assuming you want to have a context menu for the rows of your DataGrid, you can add the ContextMenu property to your DataGridRow, for example:
<DataGrid>
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Setter Property="ContextMenu" Value="{StaticResource theContextMenu}" />
</Style>
</DataGrid.RowStyle>
</DataGrid>
Then add the context menu itself in the resource dictionary:
<Window.Resources>
<ResourceDictionary>
<ContextMenu x:Key="theContextMenu">
<MenuItem Header="Menu Item 1" Click="menuItem1_Click">
</MenuItem>
<MenuItem Header="Menu Item 2" Click="menuItem2_Click">
</MenuItem>
</ContextMenu>
</ResourceDictionary>
</Window.Resources>
Then write a click event handler for each menu item to execute your method:
private void menuItem1_Click(object sender, RoutedEventArgs e)
{
// execute your method..
}
private void menuItem2_Click(object sender, RoutedEventArgs e)
{
// execute your method..
}
You could bind datacontext content to a propertie and than fill It (propertie) in your Button event. Don't forget to set Update condition in Contextmenu binding (xaml)
In my view the best form of work this out is adding an ContextMenu for each row of DataGrid, we can do it in the following way:
In the XAML, place in your DataGrid an listener to event LoadingRow:
<!-- resume version of declaration your DataGrid -->
<DataGrid x:Name="Squadre_DataGrid" LoadingRow="Squadre_DataGrid_LoadingRow" />
In the CodeBehind, come on add the ContextMenu for each row:
private void Squadre_DataGrid_LoadingRow(object sender, DataGridRowEventArgs e)
{
ContextMenu _contextMenu = new ContextMenu();
MenuItem mia = new MenuItem();//item 1
MenuItem mib = new MenuItem();//item 2
....
_contextMenu.Add(mia);
_contextMenu.Add(mib);
....
e.Row.ContextMenu = _contextMenu;//add context menu to row
}

How to get Button as Parent on MenuItemFlyoutItem_Click?

I'm building a WinRT Universal app and I have a button and a MenuFlyout attached to it - I'm trying to get the Name and Tag of the button.
XAML:
<MenuFlyout x:Key="FlyOutResource">
<MenuFlyoutItem Text="pin to start" Click="PinToStart_Click"/>
</MenuFlyout>
<Button x:Name="ButtonName" Tag="BUTTON TAG" FlyoutBase.AttachedFlyout="{StaticResource FlyOutResource}" Holding="Button_Holding"/>
C#:
private void Button_Holding(object sender, Windows.UI.Xaml.Input.HoldingRoutedEventArgs e)
{
FlyoutBase.ShowAttachedFlyout(sender as FrameworkElement);
}
private void PinToStart_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
var menuFlyoutItem = sender as MenuFlyoutItem;
if (menuFlyoutItem != null)
{
????
}
}
How do I get the name of the button (of which the FlyOut is attached to)? DataContext doesn't work.
Kind regards,
Niels
I am in UWP but am hitting the same issue and do not see a way around it from within the PinToStart_Click Handler.
In your solution, you at least see which button opened the flyout within the Button_Holding handler. I'd recommend storing a reference to the sender in the Button_Holding handler and then access that reference within the PinToStart click handler.
var tempParent = Windows.UI.Xaml.Media.VisualTreeHelper.GetParent(child as FrameworkElement);
I hope this will work for you.
For future reference, I leave a solution
If you name your MenuFlyout:
<Button.Flyout>
<MenuFlyout x:Name="MenuFlyoutContainer">
<MenuFlyoutItem Tapped="OnMenuFlyoutItem"/>
</MenuFlyout>
</Button.Flyout>
Then on the tapped event you can search for it:
private void OnDeletePressed(object sender, TappedRoutedEventArgs e)
{
var item = (sender as MenuFlyoutItem);
var itemDataContext = item.DataContext;
FrameworkElement parent = (item.FindName("MenuFlyoutContainer") as MenuFlyout);
}
And voila you have your MenuFlyout instance.
Tested inside DataTemplates on UWP.

Contextmenu - disable right click to open it

I have such xaml code:
<Grid x:Name="boardGrid">
<Grid.ContextMenu>
<ContextMenu Opacity="0.7" x:Name="menuContext">
</ContextMenu>
</Grid.ContextMenu>
</Grid>
I generate grid's items in code behind. What I want is to disable context menu opening on right click. I want to open it when certains conditions occur.
This is what I have in .cs file:
generating Unit's objects and putting them into Grid;
each object has unit.MouseRightButtonUp += unit_MouseRightButton
void unit_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
{
if (CurrentGame.CurrentPlayer.HasTurn == false) return;
.....
ContextMenu.IsOpen = true;
}
So it means that Contextmenu should be open only if condition is fulfilled but it opens anyway.
You can set the attached property ContextMenuService.IsEnabled to false. Then you can manually popup the ContextMenu.
You must set that property for the GUI element that owns the menu. Setting it for the menu itself will do nothing.
<Grid x:Name="boardGrid" ContextMenuService.IsEnabled="false">
<!-- ... -->
</Grid>
void unit_MouseRightButtonUp(object sender, MouseButtonEventArgs e) {
if (CurrentGame.CurrentPlayer.HasTurn == false) return;
.....
boardGrid.ContextMenu.IsOpen = true;
}

ContextMenu disappears immediately after appearing

I have a context menu but it is disappearing instantly after it shows up.
<TextBlock Name="InputtedAddress" Text="{Binding Path=InputtedAddress}" MouseDown="InputtedAddress_MouseDown"/>
System.Windows.Controls.ContextMenu thisMenu;
private void InputtedAddress_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.RightButton == MouseButtonState.Pressed)
{
thisMenu = new System.Windows.Controls.ContextMenu();
MenuItem thisMenuItem = new MenuItem() { Header = "Zoom to Incident" };
thisMenuItem.Click += new RoutedEventHandler(thisMenuItem_Click);
thisMenu.Items.Add(thisMenuItem);
thisMenu.IsOpen = true;
}
}
It's likely because you're not marking the MouseDown event to handled. Set e.Handled to true and it will no longer propagate and your ContextMenu will stay open.
That said, this is an awful way to assign a ContextMenu in the first place. Why not just do this:
<TextBlock ...>
<TextBlock.ContextMenu>
<ContextMenu>
<MenuItem Header="Zoom to Incident" Click="thisMenuItem_Click"/>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
You should assign your menu to the ContextMenu property of your TextBlock so that the opening and positioning will be taken care of for you. You also don't need to create the menu in each MouseDown; just create it once and assign it to the ContextMenu property.
In XAML:
<TextBlock
Name="InputtedAddress"
Text="{Binding Path=InputtedAddress}"
>
<TextBlock.ContextMenu>
<ContextMenu>
<MenuItem
Header="Zoom to Incident"
Click="ContextMenu_Click"
/>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
If you do want to show it manually you will need to position it before showing it by setting the PlacementTarget property, something like this:
private void InputtedAddress_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.RightButton == MouseButtonState.Pressed)
{
thisMenuPlacementTarget = InputtedAddress;
thisMenu.IsOpen = true;
}
}
P.S. "Inputted" is not a word :)

Categories

Resources