WPF Change style of System ContextMenu - wpf

Is it possible to style the System ContextMenu?
If it does, I would appreciate if you could tell me how..
I want to change its style, not to add items/disable items.
I am talking about this:
EDIT:
This is the style I am using right now (this is just an example - to see if it's possible to style the system ContextMenu:
<Style TargetType="{x:Type ContextMenu}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ContextMenu}">
<Grid Margin="0,0,5,5">
<Border x:Name="SubMenuBorder" BorderBrush="Red" BorderThickness="1" Background="Yellow" SnapsToDevicePixels="True" Padding="2">
<StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Cycle"/>
<Border.Effect>
<DropShadowEffect Color="{StaticResource DropShadowColor}" Opacity="0.60" ShadowDepth="3"/>
</Border.Effect>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The style is located in the App.xaml file - it affect all the ContextMenus in my app except the System ContextMenu

Related

WPF Progressbar style text

I have a style for a progressbar that shows some text only on the PART_Indicator section:
<Style x:Key="{x:Type ProgressBar}" TargetType="{x:Type ProgressBar}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ProgressBar}">
<Grid MinHeight="14" MinWidth="200">
<Border Name="PART_Track" CornerRadius="15" Background="{StaticResource PressedBrush}" BorderBrush="{StaticResource SolidBorderBrush}" BorderThickness="1" />
<Border Name="PART_Indicator" CornerRadius="15" Background="#CEAC2D" BorderBrush="#CEAC2D" BorderThickness="1" HorizontalAlignment="Left" >
<Viewbox>
<TextBlock TextAlignment="Center" Background="Transparent" FontFamily="Times" Foreground="Black" Margin="2,2,2,2"
Text="{Binding ProgressText}"/>
</Viewbox>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I have a few bars and each one should show a different kind of text (50%, 2/8, etc..) and that of course is handled by the VM.
My question is how to use this style for all the bars but differentiate only that textblock text. I presume the binding is not correct .. I probably need a TemplateBinding, but to what property?

WPF Creating DataTemplate for a control that doesn't have a DataTemplate property

I'm creating a custom TickBar for a Slider. This CustomTickBar allows me to put different markers on the Slider. I'm gonna use the following model:
Interface IModel
{
string Id;
}
Class Model1 : IModel
{
string Id;
string SomeProperty;
}
Class Model2 : IModel
{
string Id;
string SomeOtherProperty;
}
The idea is I provide a List<IModel> to this TickBar control and based on the type of IModel the marker icon would change; e.g. for Model1 it would be a triangle and for Model2 it would be a rectangle. I understand this would be possible using a DataTemplate. But WPF TickBar doesn't have a DataTemplate property. Now is there a way I can do this using a DataTemplate property and subclassing TickBar?
Note: I understand I can create custom tick using OnRender(), but I'm trying to check if there's a way to do it by writing as less code-behind as possible.
TickBar does not have default style, so it looks like using OnRender is the way they designed it.
Another solution I'm think about, would be:
Create custom control, you own TickBar. Maybe inherit from TickBar.
You can set your own style for this custom TickBar, even based on some of your model data.
Use themes/generic.xaml and this code to apply custom style for your control:
static void MyCustomTickBar() {
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyCustomTickBar), new FrameworkPropertyMetadata(typeof(MyCustomTickBar)));
}
Edit template of Slider and use you new TickBar instead of built in one.
Here is default template for Slider. I used style snooper to extract it. Sorry, I could not provide it in my answer, it's too long.
Try to create a style for the slider first.
e.g. Something like this:
<Window.Resources>
<SolidColorBrush x:Key="HorizontalSliderTrackNormalBackground" Color="#FFE7EAEA"/>
<LinearGradientBrush x:Key="HorizontalSliderTrackNormalBorder" EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#FFAEB1AF" Offset="0.1"/>
<GradientStop Color="#FFAEB1AF" Offset=".9"/>
</LinearGradientBrush>
<Style x:Key="SliderRepeatButtonStyle" TargetType="{x:Type RepeatButton}">
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="IsTabStop" Value="false"/>
<Setter Property="Focusable" Value="false"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RepeatButton}">
<Rectangle Fill="Transparent"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="CustomThumbForSlider" TargetType="{x:Type Thumb}">
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Ellipse Fill="#009EFF" Stroke="#009EFF" Height="14" Width="14"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="MyCustomStyleForSlider" TargetType="{x:Type Slider}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Slider}">
<Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="Auto" MinHeight="{TemplateBinding MinHeight}"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TickBar x:Name="TopTick" Visibility="Collapsed" Fill="{TemplateBinding Foreground}" Placement="Top" Height="10" Grid.Row="2"/>
<TickBar x:Name="BottomTick" Visibility="Collapsed" Fill="{TemplateBinding Foreground}" Placement="Bottom" Height="10" Grid.Row="2"/>
<Border x:Name="TrackBackground"
Background="{StaticResource HorizontalSliderTrackNormalBackground}"
BorderBrush="{StaticResource HorizontalSliderTrackNormalBorder}"
BorderThickness="2" CornerRadius="1"
Margin="5,0" VerticalAlignment="Center" Height="10.0" Grid.Row="1" >
<Canvas Margin="-6,-2">
<Rectangle Visibility="Hidden" x:Name="PART_SelectionRange" Height="6.0"
Fill="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"
Stroke="{DynamicResource {x:Static SystemColors.ControlDarkDarkBrushKey}}"
StrokeThickness="2.0"/>
</Canvas>
</Border>
<Track x:Name="PART_Track" Grid.Row="1" >
<Track.DecreaseRepeatButton>
<RepeatButton Style="{StaticResource SliderRepeatButtonStyle}" Command="{x:Static Slider.DecreaseLarge}"/>
</Track.DecreaseRepeatButton>
<Track.IncreaseRepeatButton>
<RepeatButton Style="{StaticResource SliderRepeatButtonStyle}" Command="{x:Static Slider.IncreaseLarge}"/>
</Track.IncreaseRepeatButton>
<Track.Thumb>
<Thumb x:Name="Thumb" Style="{StaticResource CustomThumbForSlider}" Background="Black"/>
</Track.Thumb>
</Track>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
You can then define a Slider which uses the style:
<Slider Name="CustomSlider" Style="{StaticResource MyCustomStyleForSlider}"/>
In order to change the style depending on some properties you can add a datatrigger. just replace the existing style with a new one:
<Style x:Key="CustomThumbForSlider" TargetType="{x:Type Thumb}">
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Ellipse Fill="#009EFF" Stroke="#009EFF" Height="14" Width="14"/>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsDifferent}" Value="True">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Ellipse Fill="#009055" Stroke="#009055" Height="14" Width="14"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
This new Style is going to change the appearance when the datacontext of slider has a different value for the property "IsDifferent".
<Slider Name="CustomSlider" Style="{StaticResource MyCustomStyleForSlider}" DataContext="{Binding Path=MyContext}"/>
Of course it would be possible to replace the green ellipse with a different shape of your liking and also use a different property.
For the templating problem it is usally best to use a ControlTemplate or alternativly a ContentControl whose DataTemplate can be set freely and which will act as a parent for your own controls.
I've recently tried overriding onrender for a custom slider myself and it's tricky. I wouldn't go that route.
I suggest you consider adding another control to hold the markers and make that match the height or width of your slider.
If your "ticks" at fixed then that could be just a uniformgrid containing paths and you use a resource to define their data using a DynamicResource geometry. You can switch out the geometry by merging different ones or datatemplate it.

Button Background property not working

I have a button with a style in my code. The Style is in the resources of the .xaml file:
<Style x:Key="RoundCorner" TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border CornerRadius="8" BorderBrush="#006AB6" BorderThickness="1" Name="border" >
<Grid x:Name="grid" >
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" ></ContentPresenter>
</Grid>
</Border>
<ControlTemplate.Triggers></ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And here's the code for the button:
<Button Name="btnZ" Background="Red" Content="{Binding Z}" Grid.Column="2" Style="{DynamicResource RoundCorner}" Visibility="{Binding Path=IsButtonVisible, Converter={StaticResource boolToVisibilityConverter}}"/>
The background property for the button, in which I set the property to Red - doesn't work. Why is that happening?
You have to map the Background of the Button to the Background of the inner ControlTemplate (whose the root visual is the Border) using TemplateBinding (for convenience):
<ControlTemplate TargetType="{x:Type Button}">
<Border CornerRadius="8" BorderBrush="#006AB6" BorderThickness="1"
Name="border"
Background="{TemplateBinding Background}"
/>
<!-- ... -->
</ControlTemplate>

WPF Template Inheritance

I created a button. My basic requirements are rounded thicker border, with more than one color (i.e. for Buy/Sell buttons)
I was hoping that i could create the template once, and than just override the border brush like this:
<Style x:Key="BorderButton">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border BorderThickness="2"
BorderBrush="Red"
CornerRadius="3"
Background="{x:Null}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="GreenBorderButton" BasedOn="{StaticResource BorderButton}" TargetType="{x:Type Button}">
<Setter Property="BorderBrush" Value="Green" />
</Style>
but they both produce the same style.
Do i need to write out the whole template every time? seems like unnecessary code repetition (especially if 3-4 colors are desired). Hoping there is some way to inherit a template.
Your code is very close to working; the issue is that GreenBorderButton is applying the BorderBrush to the button itself, not the Border in the overridden Template.
To fix this, simply change the Border's BorderBrush to use the parent Button's BorderBrush. You can do this using a TemplateBinding like so:
<Style x:Key="BorderButton">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="border"
BorderThickness="2"
BorderBrush="{TemplateBinding Property=BorderBrush}"
CornerRadius="3"
Background="{x:Null}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Then, you can either use the same overridden styles like you have, or you could simply do:
<Button Style="{StaticResource BorderButton}" BorderBrush="Blue" Content="Blue" />

wpf textbox flat border style

need to have flat border style for wpf based textbox... really surprised to see there is no easy way to get this like was in winforms textbox BorderStyle.FixedSingle
is there any easy way to get this done for wpf textbox
The way to do this is to use a control template to draw the border yourself. You can do this in many different ways, heres a couple for you to look at.
The quick hack approach:
<TextBox>
<TextBox.Template>
<ControlTemplate TargetType="{x:Type TextBox}">
<Grid>
<Rectangle Stroke="{StaticResource ResourceKey=detailMarkBrush}" StrokeThickness="1"/>
<TextBox Margin="1" Text="{TemplateBinding Text}" BorderThickness="0"/>
</Grid>
</ControlTemplate>
</TextBox.Template>
</TextBox>
and then theres using resources...
<ResourceDictionary>
<Color x:Key="detailMark">#FFA1A9B3</Color>
<SolidColorBrush x:Key="detailMarkBrush" Color="{StaticResource ResourceKey=detailMark}" />
<Style x:Key="flatTextBox" TargetType="{x:Type TextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Grid>
<Rectangle Stroke="{StaticResource ResourceKey=detailMarkBrush}" StrokeThickness="1"/>
<TextBox Margin="1" Text="{TemplateBinding Text}" BorderThickness="0"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
and then you can use the style:
<TextBox Style="{StaticResource ResourceKey=flatTextBox}" />
<TextBox BorderThickness="1" BorderBrush="Black">
just try this by black or gray
This is better way to me, make a custom template with border, to override the default one.
And most important make ScrollViewer named PART_ContentHost, to fit inner TemplatePart, and for any other features work like default.
simular to example from MSDN:
<Style TargetType="TextBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBoxBase}">
<Border CornerRadius="2" Padding="2" Background="#19212F" BorderBrush="Red" BorderThickness="1">
<ScrollViewer Margin="0" x:Name="PART_ContentHost" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Resources