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>
Related
I am reading a book on WPF as I'm trying to learn it.
There is an example of a button below. This makes sense apart from one line, below.
<ContentControl Margin=”2” Content=”{TemplateBinding Content}”/>
The book says the below,
Figure 14.9 shows what two Buttons look like with this new control template applied.
One Button has simple “OK” text content, and the other has an Image. In both cases, the content is reflected in the new visuals as expected.
However I can't see how to get an image to show on the button? I have drawn a triangle below that I want to be in the centre of the button but I can't get it to appear.
My drawing
<Polygon x:Key="playTriangle" Stroke="Black" Fill="Black">
<Polygon.Points>
<Point X="10" Y="40"/>
<Point X="40" Y="25"/>
<Point X="10" Y="10"/>
</Polygon.Points>
</Polygon>
Book Example
<ControlTemplate x:Key="buttonTemplatePlay" TargetType="{x:Type RibbonButton}">
<Grid Height="60" Width ="60">
<Ellipse x:Name="outerCircle">
<Ellipse.Fill>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0" Color="Blue"/>
<GradientStop Offset="1" Color="Red"/>
</LinearGradientBrush>
</Ellipse.Fill>
</Ellipse>
<Ellipse Margin="5">
<Ellipse.Fill>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0" Color="White"/>
<GradientStop Offset="1" Color="Transparent"/>
</LinearGradientBrush>
</Ellipse.Fill>
</Ellipse>
<Viewbox>
<ContentControl Margin="5" Content="{TemplateBinding Content}"/>
</Viewbox>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="outerCircle" Property="Fill" Value="Green"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="RenderTransform">
<Setter.Value>
<ScaleTransform ScaleX=".9" ScaleY=".9"/>
</Setter.Value>
</Setter>
<Setter Property="RenderTransformOrigin" Value=".5,.5"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
You should set the polygon (or any other content for that matter) as the button's content:
<RibbonButton>
<RibbonButton.Content>
<Polygon Stroke="Black" Fill="Black">
<Polygon.Points>
<Point X="10" Y="40"/>
<Point X="40" Y="25"/>
<Point X="10" Y="10"/>
</Polygon.Points>
</Polygon>
</RibbonButton.Content>
</RibbonButton>
Note that I removed the x:Key="playTriangle" attribute
If the polygon is defined in a resource dictionary, you should reference it using StaticResourceExtension instead:
<RibbonButton Content={StaticResource ResourceKey=playTriangle}" />
One way or another, the key point is that you should use RibbonButton.Content property to set content of the button.
I have a Style defined for my DataGridCell
<Style x:Key="MYDGCellStyle" TargetType="{x:Type DataGridCell}">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="Template" Value="{DynamicResource MYDGCellControlTemplate}" />
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsReadOnly}" Value="True">
<Setter Property="Background">
<Setter.Value>
<SolidColorBrush Color="Gray" Opacity="0.3" />
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
<ControlTemplate x:Key="MYDGCellControlTemplate" TargetType="{x:Type DataGridCell}">
<Grid x:Name="CellGrid">
<Border Background="{TemplateBinding Background}">
<ContentPresenter VerticalAlignment="Center" Margin="4,0,6,0" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsFocused" Value="true">
<Setter Property="Background" TargetName="CellGrid">
<Setter.Value>
<LinearGradientBrush Opacity="2" StartPoint="0,0.5" EndPoint="1,0.5">
<GradientStop Offset="0" Color="Fuchsia" />
<GradientStop Offset="0.2" Color="Transparent" />
<GradientStop Offset="0.8" Color="Transparent" />
<GradientStop Offset="1" Color="Fuchsia" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
During Runtime I add additional Triggers for specific Columns like this in my Code
Style Sty = null;
if (Sty == null)
{
Sty = new Style(typeof(DataGridCell));
Sty.BasedOn = (Style)Application.Current.TryFindResource("MYDGCellStyle");
}
DataTrigger t = new DataTrigger();
t.Binding = new Binding("ProductionStatus");
t.Value = "I";
Setter s = new Setter();
s.Property = DataGridCell.BackgroundProperty;
s.Value = new SolidColorBrush(Colors.Gold) { Opacity = 0.5 };
t.Setters.Add(s);
Sty.Triggers.Add(t);
DGC.CellStyle = Sty;
But if I focus one of the Cells where a DataTrigger I added in my Code is triggerd the Color isn't displayed correctly.
How can I display the fuchsia Sides in front of the Gold Background?
Grey Cell Focused:
Gold Cell Focused:
UPDATE
<ControlTemplate x:Key="MYDGCellControlTemplate" TargetType="{x:Type DataGridCell}">
<Grid>
<Grid Grid.ZIndex="99" x:Name="CellGrid"/>
<Border Grid.ZIndex="98" Background="{TemplateBinding Background}">
<ContentPresenter VerticalAlignment="Center" Margin="4,0,6,0" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsFocused" Value="true">
<Setter Property="Background" TargetName="CellGrid">
<Setter.Value>
<LinearGradientBrush Opacity="2" StartPoint="0,0.5" EndPoint="1,0.5">
<GradientStop Offset="0" Color="Fuchsia" />
<GradientStop Offset="0.1" Color="#00FF00FF" />
<GradientStop Offset="0.9" Color="#00FF00FF" />
<GradientStop Offset="1" Color="Fuchsia" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
Your problem might be, that you apply a golden color brush above the fuchsia edges, so they get tinted by 50% of gold.
s.Value = new SolidColorBrush(Colors.Gold) { Opacity = 0.5 };
Additionally you should be aware that using Transparent in XAML means "white with no opacity", so if you want to fade out funchsia you should not fade to transparent white, but to transparent fuchsia instead.
White: #FFFFFFFF
Transparent: #00FFFFFF
Fuchsia opaque: #FFFF00FF
Fuchsia transparent: #00FF00FF
To enforce the z-order you could use an additional container around the item given and apply the status here "during runtime". Anyway this will not be an MVVM approach.
The better way might be to define a custom template-parameter (bool IsSpecificColumn) in your XAML, which will be set in your code "during runtime". Using MultiTrigger you can also define a third state for gold+fuchsia.
If you have to combine even more states you should let WPF do the job and use the approach with the boxed containers mentioned above together with template-parameters.
Try creating a new "IsFocused" trigger in your new style(I ProductionStatus)like this:
<Trigger Property="IsFocused" Value="true">
<Setter Property="Background" TargetName="CellGrid">
<Setter.Value>
<LinearGradientBrush Opacity="2" StartPoint="0,0.5" EndPoint="1,0.5">
<GradientStop Offset="0" Color="Fuchsia" />
<GradientStop Offset="0.2" Color="Gold" />
<GradientStop Offset="0.8" Color="Gold" />
<GradientStop Offset="1" Color="Fuchsia" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
I know you are doing it on code behind, but I think you'll understand me(easyer to copy-paste).
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 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.
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