Sub-context menu for WPF - c#

I want to create sub-contextmenu for Filters in my datagrid. How can I do that? Here is my code:
<DataGrid x:Name="DataGridSuppliers" Margin="10" ItemsSource="{Binding}" IsReadOnly="True" >
<DataGrid.ContextMenu>
<ContextMenu>
<MenuItem Header="Create Supplier" Click="btnCreateSupplier_Click" />
<MenuItem Header="Edit Supplier" Click="btnEditSupplier_Click" />
<MenuItem Header="Filters" />
</ContextMenu>
</DataGrid.ContextMenu>
</DataGrid>

Create nested sub menuItems inside Filters, that's all what you want:
<ContextMenu>
<MenuItem Header="Create Supplier" Click="btnCreateSupplier_Click"/>
<MenuItem Header="Edit Supplier" Click="btnEditSupplier_Click"/>
<MenuItem Header="Filters">
<MenuItem Header="Sub Filter 1"/>
<MenuItem Header="Sub Filter 2"/>
<MenuItem Header="Sub Filter 3"/>
</MenuItem>
</ContextMenu>

Related

Flyout c# using mahapps

Hello I am currently using library Mahapps but I have some problems. How can I pop out the flyout when clicking the "Menu 1" MenuItem? I tried with the following code but it did not work.
<ListBox.ContextMenu>
<ContextMenu>
<MenuItem x:Name="FlyoutOverview" Header="Menu 1" IsCheckable="True" Click="flyoutOverview">
<MenuItem.Icon>
<iconPacks:PackIconModern Kind="GlobeWire"/>
</MenuItem.Icon>
</MenuItem>
<Separator/>
<MenuItem Header="Menu 2"/>
<Separator/>
<MenuItem Header="Menu 3">
<MenuItem.Icon>
<iconPacks:PackIconModern Kind="People"/>
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Menu 4">
<MenuItem.Icon>
<iconPacks:PackIconModern Kind="UserDelete"/>
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Menu 5">
<MenuItem.Icon>
<iconPacks:PackIconModern Kind="ControlResume"/>
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</ListBox.ContextMenu>
</ListBox>
If you have followed the tutorial links I provided then I suppose you are able to create a simple View and its ViewModel.
The View can be a Window and has its Grid content like this:
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Controls:FlyoutsControl Grid.Column="1">
<Controls:Flyout x:Name="yourMahAppFlyout" Header="Flyout" Background="AliceBlue" Position="Right" Width="350"
IsOpen="{Binding ElementName=FlyoutOverview, Path=IsChecked}">
<TextBlock Text="My Flyout is here" />
</Controls:Flyout>
</Controls:FlyoutsControl>
<ListBox Grid.Row="0" Grid.Column="0" ItemsSource="{Binding NameList}">
<ListBox.ContextMenu>
<ContextMenu>
<MenuItem x:Name="FlyoutOverview" Header="Menu 1" IsCheckable="True"
IsChecked="{Binding IsMenuItem1Checked}">
<MenuItem.Icon>
<iconPacks:PackIconModern Kind="GlobeWire"/>
</MenuItem.Icon>
</MenuItem>
<Separator/>
<MenuItem Header="Menu 2"/>
<Separator/>
<MenuItem Header="Menu 3">
<MenuItem.Icon>
<iconPacks:PackIconModern Kind="People"/>
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Menu 4">
<MenuItem.Icon>
<iconPacks:PackIconModern Kind="UserDelete"/>
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Menu 5">
<MenuItem.Icon>
<iconPacks:PackIconModern Kind="ControlResume"/>
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</ListBox.ContextMenu>
</ListBox>
</Grid>
The ViewModel can have these properties:
public MainWindowViewModel()
{
NameList = new ObservableCollection<string>()
{
"John", "Micheal", "Jack"
};
}
public ObservableCollection<string> NameList { get; set; }
public bool IsMenuItem1Checked
{
get { return _isMenuItem1Checked; }
set { SetProperty(ref _isMenuItem1Checked, value); }
}
The first menu item in the listbox binds its "IsChecked" property to "IsMenuItem1Checked" in ViewModel, and FlyOut "IsOpen" property binds to "IsChecked" of that menu item.

How to get PlacementTarget.Content in ContextMenu?

I have a situation, where I have to get Content from ContextMenu's Button. Something like this:
<Button Content="Test" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="75">
<Button.ContextMenu>
<ContextMenu>
<MenuItem Header="{Binding RelativeSource={RelativeSource Self}, Path=PlacementTarget.Content}"/>
</ContextMenu>
</Button.ContextMenu>
</Button>
But.. that doesn't work. The problem can be easily solved with the button's Tag, but the Tag is in use already:
<Button Content="Test" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="75"
Tag="{Binding DataContext, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type StackPanel}, AncestorLevel=2}}">
<Button.ContextMenu>
<ContextMenu DataContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
<MenuItem Header="{Binding RelativeSource={RelativeSource Self}, Path=PlacementTarget.Content}"/>
<MenuItem Header="Option 2" />
</ContextMenu>
</Button.ContextMenu>
</Button>
I'm using Tag to get main DataContext. Yet I still need the content of the button.
Why getting "Tag" from Placement target works, but "Content" does not?
How can I get it?
MenuItem doesn't have "PlacementTarget" property, bidning to Self doesn't work. There should be "System.Windows.Data Error: 40 : BindingExpression path error: 'PlacementTarget' property not found on 'object' 'MenuItem'" warning in Output.
Change the path:
<ContextMenu DataContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
<MenuItem Header="{Binding Path=Parent.PlacementTarget.Content, RelativeSource={RelativeSource Self}}"/>
<MenuItem Header="Option 2" />
</ContextMenu>
or RelativeSource:
<ContextMenu DataContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
<MenuItem Header="{Binding Path=PlacementTarget.Content, RelativeSource={RelativeSource AncestorType=ContextMenu}}"/>
<MenuItem Header="Option 2" />
</ContextMenu>

WPF Menu icon not showing up when I run my application. They are showing in design view

The icons in my menu are showing in the design view but not at runtime.
Why?
I have tried both with and without pack://application :,,,
<Window x:Class="Aurora4XHelper.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Aurora4XHelper"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="550">
<Grid Name="grid_Main">
<Menu IsMainMenu="True" x:Name="menu" DockPanel.Dock="Top" HorizontalAlignment="Left" Height="auto" VerticalAlignment="Top" Width="{Binding ElementName=grid_Main,Path=ActualWidth}">
<MenuItem Header="File">
<MenuItem Header="Exit" >
<MenuItem.Icon>
<Image Source="/Aurora4XHelper;component/Resources/Icons/Exit.png" />
</MenuItem.Icon>
</MenuItem>
</MenuItem>
<MenuItem Header="Design">
<MenuItem Header="Missile">
<MenuItem Header="Missile">
<MenuItem.Icon>
<Image Source="pack://application :,,,/Aurora4XHelper;component/Resources/Icons/Missile.png" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="MIRV" />
<MenuItem Header="Bouy" />
<MenuItem Header="Mine" />
</MenuItem>
<MenuItem Header="Sensor" />
<MenuItem Header="Ship" />
<MenuItem Header="Terraforming"/>
</MenuItem>
</Menu>
</Grid>
Try to remove the /Aurora4XHelper;component/ part and just put <Image Source="Resources/Icons/Exit.png" /> instead.
Also make sure the BuildAction of the png file is set to Resource.

WindowsFormHost Paint Event Not Firing

I have a panel withing a WindowsFormHost in a WPF app. Eventually i need to be able to click and draw points. I had it working fully in a separate WinForm form... but for some reason the paint event won't fire at all when Invalidate() is called! The click event is definitely firing as the message box comes up on the click. Not a peep out of the paint even though. Can't figure out why for the life of me... here's the code.
XML:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
Title="MainWindow" Height="1000" Width="1000"
WindowState="Maximized" SizeChanged="Window_SizeChanged" LocationChanged="Window_LocationChanged" Background="Gray">
<DockPanel LastChildFill="True">
<ToolBarTray DockPanel.Dock="Top">
<ToolBar Width="Auto" HorizontalAlignment="Stretch">
<Menu>
<MenuItem Header="File" VerticalAlignment="Center">
<MenuItem Header="New" Click="MenuItem_Click_3" />
<MenuItem Header="Open" Click="MenuItem_Click_4"/>
<MenuItem Header="Open Recent">
<MenuItem Header="Some Recent Files"/>
</MenuItem>
<MenuItem Header="Import H2OFate File" Click="MenuItem_Click_7"/>
<Separator/>
<MenuItem Header="Save" Click="MenuItem_Click_1" />
<MenuItem Header="Save As" Click="MenuItem_Click_5"/>
<MenuItem Header="Save without Results"/>
<MenuItem Header="Delete Unnecessary Files"/>
<Separator/>
<MenuItem Header="File Options"/>
<Separator/>
<MenuItem Header="Project Info"/>
<MenuItem Header="Supply Info" />
<Separator/>
<MenuItem Header="Print" Click="MenuItem_Click_6" />
<Separator/>
<MenuItem Header="Reload Current File"/>
<MenuItem Header="Exit CTRL+Q" Click="MenuItem_Click"/>
</MenuItem>
<MenuItem Header="Network Design" VerticalAlignment="Center">
<MenuItem Header="Something" Click="MenuItem_Click_8"/>
</MenuItem>
<MenuItem Header="Run Analysis" VerticalAlignment="Center">
<MenuItem Header="Run" Click="MenuItem_Click_2"/>
</MenuItem>
<MenuItem Header="View Results" VerticalAlignment="Center">
<MenuItem Header="Numeric"/>
<MenuItem Header="X-Y Plots"/>
<MenuItem Header="Contours"/>
<MenuItem Header="Reports"/>
</MenuItem>
<MenuItem Header="Facilities Management" VerticalAlignment="Center">
<MenuItem Header="Some Item"/>
<MenuItem Header="Hydraulics"/>
<MenuItem Header="Contamination"/>
<MenuItem Header="Sensor Placement"/>
</MenuItem>
<MenuItem Header="Tools/Databases" VerticalAlignment="Center">
<MenuItem Header="Some Item"/>
<MenuItem Header="Hydraulics"/>
<MenuItem Header="Contamination"/>
<MenuItem Header="Sensor Placement"/>
</MenuItem>
<MenuItem Header="Help" VerticalAlignment="Center">
<MenuItem Header="Some Item"/>
<MenuItem Header="Help"/>
<MenuItem Header="Units"/>
<MenuItem Header="Demo Examples"/>
<MenuItem Header="Tutorial"/>
<MenuItem Header="How To"/>
<MenuItem Header="About"/>
</MenuItem>
</Menu>
</ToolBar>
<ToolBar>
<Button Height="38" Width ="50" VerticalAlignment="Center" Click="Button_Click_1">
<Ellipse Width="25" Height="25" Fill="Blue" Stroke="Black" VerticalAlignment="Center"/>
</Button >
<Button Height="38" Width ="50" VerticalAlignment="Center" Click="Button_Click_1">
<Rectangle Width="38" Fill="Red" Height="7" Stroke="Black"/>
</Button >
<Button Height="38" Width ="50" VerticalAlignment="Center" Click="Button_Click_2">
<Polygon Fill="Yellow" Stroke="Black" Points="0,10 30,10 30,0 28,0 28,3 2,3 2,0 0,0" VerticalAlignment="Center"/>
</Button >
<Button Height="38" Width ="50" VerticalAlignment="Center" Click="Button_Click_3">
<Polygon Stroke="Black" Fill="Green" VerticalAlignment="Center" Points="22,0 22,7 15,7 15,15 9,15 9,7 0,7 0,0 "/>
</Button >
</ToolBar>
</ToolBarTray>
<TabControl Width ="1000" DockPanel.Dock="Left">
<TabItem Header="Map">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<WindowsFormsHost Grid.Row="0" x:Name="wfPanel" >
<WindowsFormsHost.Child>
<wf:Panel x:Name="wfSurface" MouseClick="wfSurface_MouseClick"/>
</WindowsFormsHost.Child>
</WindowsFormsHost>
</Grid>
</TabItem>
<TabItem Header="Map Settings">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="250"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Button Content="Testing 123"/>
</Grid>
</TabItem>
</TabControl>
<TabControl DockPanel.Dock="Right">
</TabControl>
</DockPanel>
C#
private void wfSurface_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
Graphics g;
g = wfSurface.CreateGraphics();
epanet epa = epanet.GetInstance();
SolidBrush s = new SolidBrush(System.Drawing.Color.Blue);
g.FillEllipse(s, Convert.ToInt32(epa.xCord), Convert.ToInt32(epa.yCord), 50, 50);
g.FillEllipse(s, 400, 400, 500, 500);
MessageBox.Show("paint event fired");
}
private void wfSurface_MouseClick(object sender, System.Windows.Forms.MouseEventArgs e)
{
epanet epa = epanet.GetInstance();
epa.xCord = e.X;
epa.yCord = e.Y;
MessageBox.Show("xCord is: " + e.X.ToString());
wfSurface.Invalidate();
}
Edit:
And to further check that the paint event is the issue I added the line g.FillEllipse(s,400,400,400,400); into the click event and it successfully drew the ellipse.
Not much of a WPF guy, but my guess would be to add this:
<WindowsFormsHost.Child>
<wf:Panel x:Name="wfSurface" Paint="wfSurface_Paint"
MouseClick="wfSurface_MouseClick"/>
</WindowsFormsHost.Child>

How do I style a submenu of a ContextMenu in wpf

I can style the contextmenu (.style) containing the items and I can style the menu items fine (.ItemTemplate). But how do I style the submenu that pops out when a menuitem has menuitems?
Like:
<ContextMenu>
<MenuItem Header="Font Style">
<MenuItem Header="Under Line" IsCheckable="true"/>
<MenuItem Header="Italic" IsCheckable="true"/>
<MenuItem Header="Bold" IsCheckable="true"/>
</MenuItem>
</ContextMenu>
<ContextMenu>
<ContextMenu.Resources>
<Style x:Key="submenuStyle" TargetType="{x:Type MenuItem}">
<Setter Property="FontWeight" Value="Bold" />
</Style>
</ContextMenu.Resources>
<MenuItem Header="Font Style">
<MenuItem Style="{StaticResource submenuStyle}" Header="Under Line" IsCheckable="true"/>
<MenuItem Style="{StaticResource submenuStyle}" Header="Italic" IsCheckable="true"/>
<MenuItem Style="{StaticResource submenuStyle}" Header="Bold" IsCheckable="true"/>
</MenuItem>
</ContextMenu>
FROM Aran Mulholland's answer:
I think this is your answer. Because the submenu IS a MenuItem, just apply the style to the submenu...
<ContextMenu>
<MenuItem Head="Font Style" Style="{StaticResource submenuStyle}" ...>
<MenuItem ... />
<MenuItem ... />
</MenuItem />
</ContextMenu>

Categories