I would like to have a template property for my custom button template that includes different options which affect the content of an image.
I.e.
Close
Maximise
Restore
Minimise
So when the user of the control wants to set the type of button to maximise, they pick it out of a drop down in the property inspector then the source of the image control embedded within the button changes to "{DynamicResource MaximiseGlyph}".
How can I allow the user to select the template for the button which will then also choose the appropriate image control source?
Here's the current base code of my button template:
<Style x:Key="WindowControlButton" TargetType="{x:Type Button}">
<Style.Resources>
<BitmapImage x:Key="RestoreGlyph" CreateOptions="IgnoreImageCache" CacheOption="OnLoad" UriSource="\Restore.png"/>
<BitmapImage x:Key="MaximiseGlyph" CreateOptions="IgnoreImageCache" CacheOption="OnLoad" UriSource="\Maximise.png"/>
<BitmapImage x:Key="CloseGlyph" CreateOptions="IgnoreImageCache" CacheOption="OnLoad" UriSource="\Close.png"/>
<BitmapImage x:Key="MinimiseGlyph" CreateOptions="IgnoreImageCache" CacheOption="OnLoad" UriSource="\Minimise.png"/>
</Style.Resources>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Ellipse Fill="Black" Opacity="0.7">
<Ellipse.Stroke>
<LinearGradientBrush EndPoint="0.5,1" MappingMode="RelativeToBoundingBox" StartPoint="0.5,0">
<GradientStop Color="White" Offset="0"/>
<GradientStop Color="#FFB8B8B8" Offset="1"/>
</LinearGradientBrush>
</Ellipse.Stroke>
</Ellipse>
<Image Source="{DynamicResource RestoreGlyph}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsFocused" Value="True"/>
<Trigger Property="IsDefaulted" Value="True"/>
<Trigger Property="IsMouseOver" Value="True"/>
<Trigger Property="IsPressed" Value="True"/>
<Trigger Property="IsEnabled" Value="False"/>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
You need to create a Custom control inheriting a Button to store your new Property and allow your template to be bind to it.
You can follow this tutorial for creating a Custom Control
http://wpftutorial.net/HowToCreateACustomControl.html
Related
I am having a funny issue here with WPF and a button styled. Problem is it contains a path and isMouseOver seems to only trigger when the mouse pointer is over the path but not over the button. That is I have to move the mouse pointer over the white figure inside the button to have the button shaded. Is as if the button wouldn't exist and only the path would.
This is the code for the button:
<Button Grid.Column="5" x:Name="btnClose" Width="30" Height="30" BorderBrush="White"
BorderThickness="0" Style="{StaticResource MenuButtonStyle}"
Command="{Binding ExitCommand}">
<Path Data="M0,0 L16,16 M16,0 L0,16" Stroke="White" StrokeThickness="3"
Margin="0,1,0,0" StrokeEndLineCap="Round" StrokeStartLineCap="Round" />
</Button>
And this is the style:
<Style x:Key="MenuButtonStyle" TargetType="Button">
<Setter Property="Width" Value="80" />
<Setter Property="Height" Value="80" />
<Setter Property="Margin" Value="0,0,0,0" />
<Setter Property="FontSize" Value="13.5"/>
<Setter Property="Foreground" Value="Red"/>
<Setter Property="RenderTransformOrigin" Value="0.5,0.5"/>
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="ToolTipService.ShowOnDisabled" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border CornerRadius="2.5"
x:Name="ButtonBorder"
BorderThickness="1.2"
RenderTransformOrigin="0.5,0.5">
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0">
<Border x:Name="ButtonShine" Grid.Row="0" VerticalAlignment="Stretch"
HorizontalAlignment="Stretch" >
<!--<Border.Effect>
<DropShadowEffect ShadowDepth="1" BlurRadius="1" RenderingBias="Quality" Direction="270" />
</Border.Effect>-->
</Border>
<ContentPresenter Grid.Row="0" VerticalAlignment="Center"
HorizontalAlignment="Center" />
<Border x:Name="shadowMouseOver" Grid.Row="0" Visibility="Hidden"
VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
Background="#7F171717">
</Border>
<Border x:Name="shadowDisabled" Grid.Row="0" Visibility="Hidden"
VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
Background="#AFFFFFFF">
</Border>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="Button.IsEnabled" Value="false">
<Setter Property="Button.Foreground" Value="#FFDEDEDE" />
<Setter Property="Visibility" TargetName="shadowDisabled" Value="Visible"/>
</Trigger>
<Trigger Property="Button.IsMouseOver" Value="true">
<Setter Property="Visibility" TargetName="shadowMouseOver" Value="Visible"/>
</Trigger>
<Trigger Property="Button.IsPressed" Value="true">
<Setter Property="Button.RenderTransformOrigin" Value="0.5,0.5"/>
<Setter Property="Button.RenderTransform">
<Setter.Value>
<ScaleTransform ScaleX="0.95" ScaleY="0.95"/>
</Setter.Value>
</Setter>
<Setter Property="Visibility" TargetName="shadowMouseOver" Value="Visible"/>
<Setter Property="Background" TargetName="ButtonShine" >
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFBFBFBF" Offset="1"/>
<GradientStop Color="#FF383838"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="BorderBrush" TargetName="ButtonShine" >
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFBFBFBF" Offset="1"/>
<GradientStop Color="#FF383838"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Any ideas? Bug in WPF? Something not done properly?
This is definitely not a bug, but due to the fact that you provide no background for the control in its template for the default state; thus, the hit test fails in the region outside of the path. If you notice, both shadowMouseOver and shadowDisabled, the only two borders that provide any background, are not visible unless the appropriate events are triggered. Thus, they are not visible to hit tests. Your path, on the other hand, is visible and so it's able to trigger events.
See Hit Testing in the Visual Layer at MSDN for more information:
https://msdn.microsoft.com/library/ms752097(v=vs.100).aspx
Just in case that link fails some time in the future, here's one of the parts that pretty much summarizes what I'm trying to say here:
The purpose of the HitTest methods in the VisualTreeHelper class is to
determine whether a geometry or point coordinate value is within the
rendered content of a given object, such as a control or graphic
element. For example, you could use hit testing to determine whether a
mouse click within the bounding rectangle of an object falls within
the geometry of a circle. You can also choose to override the default
implementation of hit testing to perform your own custom hit test
calculations. The following illustration shows the relationship
between a non-rectangular object's region and its bounding rectangle.
You have a couple of options if you wish to maintain the transparent background look. Either set that background to Transparent, due to the fact that transparent objects are visible to hits tests, or set it to some color, while turning its opacity down to 0. Best place for that background would probably be at ButtonBorder (most outer border), but it'll be your decision to make.
I have a WPF program with a tabItems interfaces set on the left hand side.
What I want is that the tabItem keeps the colour as in the following picture:
Please notice where is the mouse pointer. When there the tabItem is coloured.
When going in another part of the interface on the right the tabItem looses the colour and gets embossed:
I am not sure if it helps posting my xaml file helps.
Basically I noticed that when the arrow goes on a datagrid on the right the tabItem is coloured when going on the free space it isn't.
Please notice that I don't want the tabItem to be of a particular colour, it has to follow the system palette and so to be in the correct system colour.
Thank you for any help.
Here is an Article from Microsoft describing how to use ColorTemplate with Triggers to solve your issue.
Here is the example from article in case in the future the link is down for some reason:
<Style TargetType="{x:Type TabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid>
<Border
Name="Border"
Margin="0,0,-4,0"
Background="{StaticResource LightBrush}"
BorderBrush="{StaticResource SolidBorderBrush}"
BorderThickness="1,1,1,1"
CornerRadius="2,12,0,0" >
<ContentPresenter x:Name="ContentSite"
VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Header"
Margin="12,2,12,2"
RecognizesAccessKey="True"/>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Panel.ZIndex" Value="100" />
<Setter TargetName="Border" Property="Background" Value="{StaticResource WindowBackgroundBrush}" />
<Setter TargetName="Border" Property="BorderThickness" Value="1,1,1,0" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="Border" Property="Background" Value="{StaticResource DisabledBackgroundBrush}" />
<Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource DisabledBorderBrush}" />
<Setter Property="Foreground" Value="{StaticResource DisabledForegroundBrush}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Resources:
<LinearGradientBrush x:Key="LightBrush" StartPoint="0,0" EndPoint="0,1">
<GradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#FFF" Offset="0.0"/>
<GradientStop Color="#EEE" Offset="1.0"/>
</GradientStopCollection>
</GradientBrush.GradientStops>
</LinearGradientBrush>
...
<SolidColorBrush x:Key="SolidBorderBrush" Color="#888" />
...
<SolidColorBrush x:Key="WindowBackgroundBrush" Color="#FFF" />
...
<SolidColorBrush x:Key="DisabledBackgroundBrush" Color="#EEE" />
...
<SolidColorBrush x:Key="DisabledBorderBrush" Color="#AAA" />
...
<SolidColorBrush x:Key="DisabledForegroundBrush" Color="#888" />
In WPF, I created a rectangle like this:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:DiagramDesigner"
xmlns:c="clr-namespace:DiagramDesigner.Controls"
x:Class="GeoOvwSample.RectangleGeometryRoundedCornerExample"
>
<Brush x:Key="ItemStroke">#FFD69436</Brush>
<LinearGradientBrush x:Key="ItemBrush" StartPoint="0,0" EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStop Color="#FAFBE9" Offset="0" />
<GradientStop Color="Orange" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
<Brush x:Key="ItemStroke1">#ACADCD</Brush>
<LinearGradientBrush x:Key="ItemBrush1" StartPoint="0,0" EndPoint="0,1" >
<GradientStop Color="#FEFEFE" Offset="0"/>
<GradientStop Color="#BDBEDE" Offset="1"/>
</LinearGradientBrush>
<Style x:Key="FlowChartRectangleStyle" TargetType="Rectangle">
<Setter Property="Fill" Value="{StaticResource ItemBrush}"/>
<Setter Property="Stroke" Value="{StaticResource ItemStroke}"/>
<Setter Property="StrokeThickness" Value="1"/>
<Setter Property="StrokeLineJoin" Value="Round"/>
<Setter Property="Stretch" Value="Fill"/>
<Setter Property="IsHitTestVisible" Value="False"/>
<Setter Property="SnapsToDevicePixels" Value="True"/>
</Style>
<Style x:Key="Data" TargetType="Rectangle" BasedOn="{StaticResource FlowChartRectangleStyle}">
</Style>
<Style x:Key="Data_DragThumb" TargetType="Rectangle" BasedOn="{StaticResource Data}">
<Setter Property="IsHitTestVisible" Value="true"/>
<Setter Property="Height" Value="300"/>
<Setter Property="Width" Value="200"/>
<Setter Property="Tag" Value="DataShape" />
</Style>
<s:Toolbox x:Key="FlowChartStencils" ItemSize="100,90" SnapsToDevicePixels="True"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ItemsControl.Items>
<Rectangle Style="{StaticResource Data}" ToolTip="DataTest" StrokeThickness="2">
<s:DesignerItem.DragThumbTemplate>
<ControlTemplate>
<Rectangle Style="{StaticResource Data_DragThumb}" x:Name="DataShape" Tag="DataShapeTag" />
</ControlTemplate>
</s:DesignerItem.DragThumbTemplate>
</Rectangle>
</ItemsControl.Items>
</s:Toolbox>
</ResourceDictionary>
This displays a rectangle on the panel, and I can select and drag it in my GUI. Now I want to create a kind of textblock on the shape so that it displays its tooltip value, and thus the tooltip value appears together with the shape all together. I tried to create the textblock and bind it with the rectangle shape but somehow my code is not correct. How to do it? Or is there a simpler method? Thank you.
You can simply add the TextBlock into any container control with (but after) the Rectangle element and then data bind the value of the Rectangle.ToolTip to the TextBlock.Text property. Try something like this:
<StackPanel>
<Rectangle Name="Rectangle" Style="{StaticResource Data}" ToolTip="DataTest"
StrokeThickness="2" />
<TextBlock Text="{Binding ToolTip, ElementName=Rectangle}" />
</StackPanel>
I am wondering if there is a way to customize style of windows forms application built in visual studio using c#. I have searched through the internet and couldn't find simple solution for overriding default view of the layout. Is there a way to change layout with cascading style sheets? Thanks in advance.
Windows Forms apps do not support CSS, it is used when developing websites.
In Winforms you are limited to the styles which are listed in Properties window in GUI editor, unless you'd like to override OnPaint event and do custom drawing.
Some examples are:
http://www.codeproject.com/Articles/8056/Creating-Custom-Shaped-Windows-Forms-in-NET
http://geekswithblogs.net/kobush/archive/2005/07/04/CustomBorderForms.aspx
https://customerborderform.codeplex.com/
If you are looking for more customizable solution, you can turn to WPF.
you can find answer here..
or
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
// Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
You can use a static resource such as this.
Inside button tag Style="{DynamicResource sty3dBtn}"
(You can set margins here too but sometimes thats best to do for each button depending on your own needs)
You can use xml styling. The button is set to have a dropshadow and gradient and lights up when pressed etc. As I wanted to reuse these effects with similar buttons I created a reusable style in my Application.xaml enclosed in Application - Application.Resources tags
and referenced its x:Key in style attribute of the button I wanted the effect on. You can do this on each page you choose but I think it can be better to place in a common area so its reusable throughout the scope of the class you place it in. Note the Target Type must match.
I'll post snippet of the xml style it turns a regular button into one with 3d effect. You can reference this as many times as you need. It cuts down on inline code clutter too so makes the page more readable in my opinion.
<Style x:Key="sty3dBtn" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Rectangle x:Name="GelBackground" Opacity="1" RadiusX="9" RadiusY="9"
Fill="{TemplateBinding Background}" StrokeThickness="0.35"
RenderTransformOrigin="0.5,0.5">
<Rectangle.Stroke>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="YellowGreen" Offset="0" />
<GradientStop Color="Green" Offset="1" />
</LinearGradientBrush>
</Rectangle.Stroke>
</Rectangle>
<Rectangle x:Name="GelShine" Margin="2,2,2,0" VerticalAlignment="Top"
RadiusX="6" RadiusY="6" Opacity="1" Stroke="Transparent" Height="15px">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="Yellow" Offset="0"/>
<GradientStop Color="Transparent" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Brown">
</Setter>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Fill" TargetName="GelBackground">
<Setter.Value>
<LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="Yellow" Offset="0"/>
<GradientStop Color="Green" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="RenderTransform" TargetName="GelBackground">
<Setter.Value>
<TransformGroup>
<ScaleTransform ScaleX="0.9" ScaleY="0.9"/>
</TransformGroup>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Fill" TargetName="GelBackground" Value="LightGray">
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<!-- Contains animation code-->
<Setter Property="Background" Value="Green"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="Width" Value="55"/>
<Setter Property="Height" Value="30"/>
</Style>
I have this style for a button:
<Style x:Key="ButtonStyle1" TargetType="{x:Type local:ButtonExt}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:ButtonExt}">
<Grid Name="grid" Margin="0,0,0,0">
<Rectangle Name="rectangle" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0.5">
<GradientStop Offset="1" Color="{DynamicResource button_background_gradient1}" />
<GradientStop Offset="0" Color="#FF004F96" />
</LinearGradientBrush>
</Rectangle.Fill>
<Rectangle.Effect>
<DropShadowEffect BlurRadius="3" Opacity="0.4" ShadowDepth="6" />
</Rectangle.Effect>
</Rectangle>
<Rectangle Width="0.7" Margin="0,0,43,1" HorizontalAlignment="Right" VerticalAlignment="Stretch" Stroke="#FF434343">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0.5">
<GradientStop Offset="0" Color="#FFF7F7F7" />
<GradientStop Offset="1" Color="#FFD6D6D6" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsFocused" Value="True" />
<Trigger Property="IsDefaulted" Value="True" />
<Trigger Property="Button.IsPressed" Value="True">
<Setter TargetName="grid" Property="Margin" Value="2,2,-1,-1" />
<Setter TargetName="rectangle" Property="Effect" Value="{x:Null}"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True"/>
<Trigger Property="IsPressed" Value="True" />
<Trigger Property="IsEnabled" Value="False"/>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
and another style based on this style:
<Style x:Key="ButtonStyle2" BasedOn="{StaticResource ButtonStyle1}">
<Setter Property="Rectangle.Fill">
<Setter.Value>
In the first style, I have two rectangles. In the second style, which is based on style 1, I would like to change the property of just one rectangle (which I named it "rectangle"). How can I do that?
Expose a property for the rectangle's fill in the ButtonEx class.
In the template, use {TemplateBinding} to bind the Fill to this new property.
In the derived style, set a new value to this property.