Problems with styled context menuitem - c#

I have code (below) that should produce a styled context menu. Unfortunately the menu item also shows a "white" bit that shouldn't be there (see below). I have tried styling it out but it doesn't work. Any help would be appreciated
<Style TargetType="ContextMenu">
<Setter Property="Background" Value="{StaticResource backgroundDark}" />
<Setter Property="BorderBrush" Value="{StaticResource highlight}" />
<Style.Resources>
<Style TargetType="MenuItem">
<Setter Property="Foreground" Value="Black" />
<Setter Property="Background" Value="Transparent" />
<Style.Triggers>
<Trigger Property="IsHighlighted" Value="True">
<Setter Property="Foreground" Value="{StaticResource highlightLight}" />
</Trigger>
</Style.Triggers>
</Style>
</Style.Resources>
</Style>

you will want to override the
StackPanel Margin of MenuItems
and then override with the same value the ItemsPanel
so basically you can just add 2 simple styles in addition to your style.
I have added a sample:
<Grid>
<Grid.Resources>
<ItemsPanelTemplate x:Key="GlobalMenuItemPanelTemplate">
<StackPanel Margin="-25,0,0,0" Background="White"/>
</ItemsPanelTemplate>
<Style TargetType="{x:Type ContextMenu}">
<Setter Property="ItemsPanel" Value="{StaticResource GlobalMenuItemPanelTemplate}"/>
</Style>
</Grid.Resources>
<Label Background="Bisque" Content="Right Click it" VerticalAlignment="Center" HorizontalAlignment="Center">
<Label.ContextMenu>
<ContextMenu>
<MenuItem Header="Menu item 1" />
<MenuItem Header="Menu item 2" />
<Separator />
<MenuItem Header="Menu item 3" />
</ContextMenu>
</Label.ContextMenu>
</Label>
</Grid>

Related

How to properly fire the click event in a contextmenu in WPF

So I am trying to create a click event for one of my contextmenu items but it's throwing me an error I have never seen before.
There wasnt too much information on Google and the information I saw didnt help me because I didnt understand it.
The line throwing the error is this one
GridView ColumnHeaderContainerStyle="{StaticResource GridViewColumnHeaderStyle1}"
saying
'cmndOP_Click' is not valid. 'Click' is not an event on
'System.Windows.Controls.GridView'.
Reading the error message tells me that 'Click' is not a valid event in the gridview, but its not in the gridview its in the listviewitem.
Whats causing this error and what should I do in the future to prevent this?
<ListView Margin="10,36,520,10" ScrollViewer.HorizontalScrollBarVisibility="Hidden" BorderBrush="Black" Padding="-1, -1, 1, 0" Background="Transparent" BorderThickness="1.000001" Name="lvUsers" Style="{DynamicResource ListViewStyle1}">
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu>
<MenuItem Name="cmndOP" Header="OP User" Click="cmndOP_Click"/>
<MenuItem Header="Kick User"/>
<MenuItem Header="Ban User"/>
<MenuItem Header="Send Command"/>
</ContextMenu>
</Setter.Value>
</Setter>
<Setter Property="Background" Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Border
BorderBrush="Transparent"
BorderThickness="0"
Background="{TemplateBinding Background}">
<GridViewRowPresenter HorizontalAlignment="Stretch" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Width="Auto" Margin="0" Content="{TemplateBinding Content}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="White" />
<Setter Property="Background" Value="#696969" />
<Setter Property="BorderBrush" Value="#696969" />
<Setter Property="BorderThickness" Value="0" />
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="White" />
<Setter Property="Background" Value="#696969" />
<Setter Property="BorderBrush" Value="#696969" />
<Setter Property="BorderThickness" Value="0" />
</Trigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
<ListView.View>
<GridView ColumnHeaderContainerStyle="{StaticResource GridViewColumnHeaderStyle1}">
<GridViewColumn x:Name="GridViewColumnName" Header="Name" Width="165">
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image x:Name="Image_GridViewColumnName" Width="16" Height="16" Source="Images\minecraft.png" />
<Label Content="{Binding Username}" Visibility="Visible" />
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
And this behind it
private void cmndOP_Click(object sender, RoutedEventArgs e)
{
Commands cmd = new Commands();
cmd.OpUser(lvUsers.SelectedItem.ToString());
}
EDIT
This is where the error happands.
This is also in the App.xaml because otherwise I would get another error
<Style x:Key="GridViewColumnHeaderStyle1" TargetType="{x:Type GridViewColumnHeader}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GridViewColumnHeader}">
<Border BorderThickness="0,0,0,1" BorderBrush="Black" Background="Transparent">
<TextBlock x:Name="ContentHeader" Text="{TemplateBinding Content}" Padding="5,5,5,5" Width="{TemplateBinding Width}" TextAlignment="Center" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="Foreground" Value="Black" />
<Setter Property="FontFamily" Value="Segoe UI" />
<Setter Property="FontSize" Value="12" />
</Style>
I was surprised to find that your error was reproducible from the XAML you provided. When I define the context menu as a resource and update the setter accordingly, I no longer get the error.
<ListView Margin="10,36,520,10" ScrollViewer.HorizontalScrollBarVisibility="Hidden" BorderBrush="Black" Padding="-1, -1, 1, 0" Background="Transparent" BorderThickness="1.000001" Name="lvUsers" >
<ListView.Resources>
<ContextMenu x:Key="ListViewItemContextMenu">
<MenuItem Name="cmndOP" Header="OP User" Click="cmndOP_Click" />
<MenuItem Header="Kick User"/>
<MenuItem Header="Ban User"/>
<MenuItem Header="Send Command"/>
</ContextMenu>
</ListView.Resources>
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="ContextMenu" Value="{StaticResource ListViewItemContextMenu}" />

wpf datagrid - how to remove black selected border?

I need help,
when I click at datagrid at cell, I want to select all line like in image (please look at image), but without black border. how to disable, or change color to transparent? I tried this:
<DataGrid.Resources>
<Style TargetType="DataGridCell">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
</Style>
</DataGrid.Resources>
but don't work. nothing changes.
You need to style the selected cell not just cells. To do so you need to write this inside your style tag:
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="BorderThickness" Value="0"/>
</Trigger>
</Style.Triggers>
All you need was using Triggers hope it will work for you. Also you can change background for selected cell or whatever property you want.
Following example to customize wpf datagrid (border, cell corners, etc.). You can modify it as you wish.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Page.Resources>
<Style x:Key="cellStyle" TargetType="DataGridCell">
<Setter Property="Padding" Value="0" />
<Setter Property="Margin" Value="2" />
<Setter Property="Background" Value="Black" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="DataGridCell">
<Border Background="Black" BorderThickness="0">
<Border x:Name="border"
BorderBrush="White"
BorderThickness="2"
Background="Black"
CornerRadius="5">
<ContentPresenter />
</Border>
</Border>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsSelected}" Value="true">
<Setter TargetName="border" Property="Background" Value="Orange"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="rowStyle" TargetType="DataGridRow">
<Setter Property="Padding" Value="0" />
<Setter Property="Margin" Value="0" />
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Background" Value="Black" />
</Style>
<Grid>
<DataGrid HeadersVisibility="None" GridLinesVisibility="None" SelectionMode="Single" SelectionUnit="Cell" IsReadOnly="true"
RowStyle="{StaticResource rowStyle}" CellStyle="{StaticResource cellStyle}"
Background="Black" Foreground="White" ItemsSource="{Binding MyData}" />
</Grid>
</Page>

WPF Combobox: Only the first item should be editable

Only the first item in Combobox (selectedIndex = 0) should be editable. I have got it already. But the problem is that the selected text didn't get highlighted.
Any help would be appreciated!
Code
<Window.Resources>
<Style x:Key="ComboBoxStyle" TargetType="{x:Type ComboBox}">
<Setter Property="IsEnabled" Value="True"></Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=SelectedIndex, ElementName=comboBox1}" Value="0">
<Setter Property="ComboBox.IsEditable" Value="True" />
</DataTrigger>
</Style.Triggers>
</Style>
<Style x:Key="FirstItem" TargetType="{x:Type ListBoxItem}">
<Style.Triggers>
<Trigger Property="ComboBox.AlternationIndex" Value="0" >
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
<Setter Property="FontWeight" Value="Normal"/>
<Setter Property="FontStyle" Value="Italic"/>
<Setter Property="FontFamily" Value="SEGOEWP"/>
<Setter Property="FontSize" Value="15"/>
<Setter Property="Foreground" Value="Gray"/>
<Setter Property="Opacity" Value="1"/>
<Setter Property="TextBlock.TextTrimming" Value="WordEllipsis"/>
</Trigger>
</Style.Triggers>
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Green"/>
</Style.Resources>
</Style>
</Window.Resources>
<StackPanel >
<ComboBox Name="comboBox1" Style="{StaticResource ComboBoxStyle}" Width="100" Height="38"
AlternationCount="500" ItemsSource="{Binding Items}"
ItemContainerStyle="{StaticResource FirstItem}"
SelectedItem="{Binding SelectedItem}"
SelectedIndex="{Binding SelectedIndex}"
IsTextSearchEnabled="false"
Text="{Binding NewItem, UpdateSourceTrigger=LostFocus}">
<ComboBox.InputBindings>
<KeyBinding Command="{Binding LoginCMD}" Key="Return" />
</ComboBox.InputBindings>
</ComboBox>
</StackPanel>

Why binding MenuItems to a ContextMenu doesn't display anything?

I'm beginner in MVVM and I've been trying to display MenuItems in a ContextMenu, but something seems to be wrong. I've already made a working Menu which has Itemssource bound to a collection in the viewmodel, but it doesn't work in case of the ContextMenu.
Could you guys take a look and say if I'm missing something?
Here's the Menu, which works well:
<Menu DockPanel.Dock="right" ItemsSource="{Binding Path=modes}" Background="#FF303030" Foreground="White" Height="21">
<Menu.Resources>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="Background" Value="#FF303030"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="Height" Value="21" />
<Setter Property="Visibility" Value="{Binding visibility}" />
<Setter Property="Header" Value="{Binding header}" />
<Setter Property="ItemsSource" Value="{Binding children}"/>
<Setter Property="Command" Value="{Binding action}"/>
<Setter Property="CommandParameter" Value="{Binding attachedData}"/>
</Style>
</Menu.Resources>
</Menu>
And here's the XAML of the ContextMenu, which, for some reason, doesn't display any MenuItems:
<Grid x:Name="btnMode" PreviewMouseDown="OnBtnModeMouseDown" Width="19" Height="19" Margin="0,0" DockPanel.Dock="Right">
<Canvas>
<Path Data="M0,0 L19,0 L19,19 L0,19" Margin="0,0" Fill="#FF303030"/>
<Ellipse Height="12" Margin="4,3,0,0" Width="12" Fill="#FFFDFDFD"/>
<Path Data="M1.5,1L18.5,1 L10,9.5" Margin="0,0,0,8.875" Fill="#FF303030"/>
</Canvas>
<Grid.ContextMenu>
<ContextMenu ItemsSource="{Binding Path=modes}">
<ContextMenu.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Background" Value="#FF303030"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="Height" Value="21" />
<Setter Property="Visibility" Value="{Binding visibility}" />
<Setter Property="Header" Value="{Binding header}" />
<Setter Property="ItemsSource" Value="{Binding children}"/>
<Setter Property="Command" Value="{Binding action}"/>
<Setter Property="CommandParameter" Value="{Binding attachedData}"/>
</Style>
</ContextMenu.ItemContainerStyle>
</ContextMenu>
</Grid.ContextMenu>
</Grid>
I also have a ContextMenu that has hard-coded menu items:
<Grid x:Name="btnMenu" PreviewMouseDown="OnBtnMenuMouseDown" Width="19" Height="19" Margin="0,1" DockPanel.Dock="Right">
<Canvas>
<Path Data="M0,0 L19,0 L19,19 L0,19" Margin="0,0" Fill="#FF303030"/>
<Path Data="M0,0L7,0 L3.5,7" Margin="6,7" Fill="White"/>
</Canvas>
<Grid.ContextMenu >
<ContextMenu IsVisibleChanged="OnBtnMenuPopup">
<MenuItem Name="menuFloatingWindow" Header="Floating window" Click="OnDockingMenu"></MenuItem>
<MenuItem Name="menuDockedWindow" Header="Docked window" Click="OnDockingMenu"></MenuItem>
<MenuItem Name="menuTabbedDocument" Header="Tabbed document" Click="OnDockingMenu"></MenuItem>
<MenuItem Name="menuAutoHide" Header="Auto hide" Click="OnDockingMenu"></MenuItem>
<MenuItem Name="menuClose" Header="Close" Click="OnDockingMenu"></MenuItem>
</ContextMenu>
</Grid.ContextMenu>
</Grid>
The collection of MenuItems is an ObservableCollection, defined as follows:
_menus = new ObservableCollection<MenuItem>()
{
new MenuItem(
"File", // string header
Visibility.Visible, // Visibility visibility
null, // ICommand action
null, // object attachedData (CommandParameters)
new ObservableCollection<MenuItem>() // children
{
new MenuItem(
"Exit",
Visibility.Visible,
MainWindow.exitCommand,
null,
null
)
}
),
..., // more nested MenuItems here
};
Both the working Menu and the ContextMenu have the same ObservableCollection as an ItemSource.
Here's an image showing how the controls look in the application:
Did I mess something up in XAML?
P.S.
I tried debugging the XAML at runtime using this: http://www.wpftutorial.net/DebugDataBinding.html but I couldn't see any helpful information when the breakpoint occured.

C# WPF MenuItem custom template

In Main.xaml I have these two menu items:
The first with the header = Disconnect from current
The second with the header = Quit
...
More menu items with different header texts...
In order to edit some colors of the first item I created a custom template in App.xaml:
<!--Template for Menu Items-->
<Style x:Key="MenuItemBaseStyle" TargetType="MenuItem">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Background" Value="#0a99f3" />
<Setter Property="Foreground" Value="White"/>
</Trigger>
</Style.Triggers>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type MenuItem}">
<Grid Background="{TemplateBinding Background}">
<MenuItem Header="DISCONNECT FROM CURRENT" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And in Main.xaml:
<MenuItem Header="CONNECTION">
<MenuItem Style="{StaticResource MenuItemBaseStyle}" Header="DISCONNECT FROM CURRENT" />
<MenuItem Header="QUIT"/>
</MenuItem>
Now I want to do the same for the second menu item. The problem is with the different header. If I delete the header from the template, it won't show any header even if the header text is still present in Main.xaml
How can I use this template for many menu items where the only thing that changes is the header text?
You could just use TemplateBinding on the Header property in the same way you've used it on the Background property:
<ControlTemplate TargetType="{x:Type MenuItem}">
<Grid Background="{TemplateBinding Background}">
<MenuItem Header="{TemplateBinding Header}" />
</Grid>
</ControlTemplate>
You can make an individual style for every MenuItem using a StyleSelector.
public class MyStyleSelector : StyleSelector
{
public override Style SelectStyle(object item, DependencyObject container)
{
var itemsControl = ItemsControl.ItemsControlFromItemContainer(container);
var index = itemsControl.ItemContainerGenerator.IndexFromContainer(container);
if (index == 0)
return (Style)itemsControl.FindResource("FirstItemStyle");
if (index == 1)
return (Style)itemsControl.FindResource("SecondItemStyle");
return base.SelectStyle(item, container);
}
}
And in your XAML
<Window x:Class="Menus.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Menus"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:MyStyleSelector x:Key="MyStyleSelector" />
<Style x:Key="FirstItemStyle" TargetType="MenuItem">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Background" Value="#0a99f3" />
<Setter Property="Foreground" Value="White"/>
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="SecondItemStyle" TargetType="MenuItem">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Background" Value="Red" />
<Setter Property="Foreground" Value="White"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<Menu ItemContainerStyleSelector="{StaticResource MyStyleSelector}">
<MenuItem Header="Menu 1" />
<MenuItem Header="Menu 2" />
<MenuItem Header="Menu 3" />
</Menu>
</Grid>
See StyleSelector here: StyleSelector

Categories