So I created a very (and I can't stress that enough) simple program since I am just starting out learning WPF.
It's so simple, in fact, that I can write it all here:
<Window x:Class="TestWPF.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="650" Width="825">
<Grid>
<StackPanel Width="125" Background="AliceBlue" Margin="0,10,200,10">
<Button Margin="5,5,5,5" Height="50" Width="100" Content="Tester" Background="Coral">
</Button>
</StackPanel>
</Grid>
But this program has a problem. The button flashes.
When I load up the program, the button is a coral colour (as expected). If I mouse over it, it turns back to the original colour (I guess that colour comes from the control that holds it? As you can see, I only specify one colour for the button.)
The issue comes when I click the button (left mouse). When I do this, the button transitions from one colour (coral) to the other (alice blue) over a period of about a second. It goes back and forth over and over. If I mouse over it in this state, it returns to the mouse over colour as it would do normally, but then when I take my mouse away from it, it starts flashing again.
To be clear: this is not about the change of colour on mouseover. I'm fine with that. After I click the button, said button transitions between two colours over and over again. The colours are coral and the mouse over colour, which of course I have not specified.
I am at a loss here. I've not told it to do this (have I?) I haven't clicked anything in the properties or written any code behind. The XAML is ALL that I have done.
Why on earth does the button flash?
Edit here are some images which show the entire thing. All code (there isn't any). The XAML, the app.xaml.cs, everything.
Edit 2 another image with all the button properties. I didn't change any, so far as I know.
The "flashing" you are experiencing probably comes from the default template of the Button. You can override it to make your Button look like a plain rectangle without any kind of effects:
<Button Margin="5,5,5,5" Height="50" Width="100" Content="Tester" Background="Coral">
<Button.Template>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Margin}">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Border>
</ControlTemplate>
</Button.Template>
</Button>
This is because of the default styles in windows.
A normal button (on windows 7) transitions from a two tone grey to a two tone blue, it's triggered by the default control template.
You can edit the control template and set the style on the button..
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero" x:Class="WpfApplication1.MainWindow"
Title="MainWindow" Height="650" Width="825">
<Window.Resources>
<Style x:Key="ButtonFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Margin="2" SnapsToDevicePixels="true" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<LinearGradientBrush x:Key="ButtonNormalBackground" EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#F3F3F3" Offset="0"/>
<GradientStop Color="#EBEBEB" Offset="0.5"/>
<GradientStop Color="#DDDDDD" Offset="0.5"/>
<GradientStop Color="#CDCDCD" Offset="1"/>
</LinearGradientBrush>
<SolidColorBrush x:Key="ButtonNormalBorder" Color="#FF707070"/>
<Style x:Key="ButtonStyle1" TargetType="{x:Type Button}">
<Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}"/>
<Setter Property="Background" Value="{StaticResource ButtonNormalBackground}"/>
<Setter Property="BorderBrush" Value="{StaticResource ButtonNormalBorder}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Themes:ButtonChrome x:Name="Chrome" BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderPressed="{TemplateBinding IsPressed}" RenderDefaulted="{TemplateBinding IsDefaulted}" SnapsToDevicePixels="true">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Themes:ButtonChrome>
<ControlTemplate.Triggers>
<Trigger Property="IsKeyboardFocused" Value="true">
<Setter Property="RenderDefaulted" TargetName="Chrome" Value="true"/>
</Trigger>
<Trigger Property="ToggleButton.IsChecked" Value="true">
<Setter Property="RenderPressed" TargetName="Chrome" Value="true"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="#ADADAD"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<StackPanel Width="125" Background="AliceBlue" Margin="0,10,200,10">
<Button Margin="5,5,5,5" Height="50" Width="100" Content="Tester" Background="Coral" Style="{DynamicResource ButtonStyle1}"/>
</StackPanel>
</Grid>
</Window>
You can now see where the other colours are coming from
Removing the attributes RenderMouseOver="{TemplateBinding IsMouseOver}" RenderPressed="{TemplateBinding IsPressed}" RenderDefaulted="{TemplateBinding IsDefaulted}" from <Themes:ButtonChrome and the <ControlTemplate.Triggers> disables this behaviour
Related
I am looking for a way to have a background image in a button with a dedicated margin. Right now I have something like this:
<Button Grid.Column="3" Margin="2,0">
<Button.Background>
<ImageBrush Stretch="Fill" TileMode="None">
<ImageBrush.ImageSource>
<DrawingImage Drawing="{StaticResource MyImage}" />
</ImageBrush.ImageSource>
</ImageBrush>
</Button.Background>
</Button>
This fills my button completely with the image. Which is (I think...) the correct behavior. Now I want to have a small margin around the background image. I didn't find a way to do this, because neither the image brush nor the drawing image offer such property. I know that I can use the button content to have an image which offers the margin, but with this approach the button image behaves strange when I put the button within a scroll viewer control (the button grows when I resize the view, but the image keeps small). What is the best way to handle this?
UPDATE *
Based on the answers below the custom style seems to be the best fit. Anyway, perhaps my problem is not really the button itself but the scrollviewer which is around the button. I have attached two images first with scrollview and second without. With the scroll viewer the image is small and does not fit the button, so perhaps this is the root cause here? Any suggestions:
Without Scrollviewer:
Set Padding, Margin is used to set the spacing outside of the control where as Padding is used to provide space inside the bounded control, and you should do the following things,
instead of Background property you have to set Content
Property of Button.
instead of ImageBrush use Image control
as a button content.
<Button
Grid.Column="3"
Width="300"
Height="30"
Margin="2,0"
Padding="5"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"
BorderBrush="Red"
Style="{DynamicResource ButtonStyle1}">
<Button.Content>
<Image Source="in.png" Stretch="Fill" />
</Button.Content>
</Button>
Setting a Margin or a Padding will not work here. The Margin is applied around the button, not in the button and the Padding is applied to the inner ContentPresenter. in other words, the padding will be around the Content, but not around the Background because that is not part of the content.
Your choices to solve the issue are:
Create a drawing that already contains the margin (which will not stay the same when rescaled).
Create the image as content of the Button, then Padding will work (recommended).
<Button Grid.Column="3" Padding="2, 0">
<Button.Content>
<Image Stretch="Fill">
<Image.Source>
<DrawingImage Drawing="{StaticResource MyImage}" />
</Image.Source>
</Image>
</Button.Content>
</Button>
Edit the default control template and style to change the way the background is applied. This can be tedious and affects other visual states than just the static one, so be careful if you choose to do this. Here is an example of how it could look like.
<SolidColorBrush x:Key="Button.Static.Background" Color="#FFDDDDDD"/>
<SolidColorBrush x:Key="Button.Static.Border" Color="#FF707070"/>
<SolidColorBrush x:Key="Button.MouseOver.Background" Color="#FFBEE6FD"/>
<SolidColorBrush x:Key="Button.MouseOver.Border" Color="#FF3C7FB1"/>
<SolidColorBrush x:Key="Button.Pressed.Background" Color="#FFC4E5F6"/>
<SolidColorBrush x:Key="Button.Pressed.Border" Color="#FF2C628B"/>
<SolidColorBrush x:Key="Button.Disabled.Background" Color="#FFF4F4F4"/>
<SolidColorBrush x:Key="Button.Disabled.Border" Color="#FFADB2B5"/>
<SolidColorBrush x:Key="Button.Disabled.Foreground" Color="#FF838383"/>
<Style x:Key="FocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Margin="2" StrokeDashArray="1 2" SnapsToDevicePixels="true" StrokeThickness="1" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ButtonStyle" TargetType="{x:Type Button}">
<Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual}"/>
<Setter Property="Background" Value="{StaticResource Button.Static.Background}"/>
<Setter Property="BorderBrush" Value="{StaticResource Button.Static.Border}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="border" Padding="{TemplateBinding Padding}" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" SnapsToDevicePixels="true">
<Border x:Name="innerBorder" Background="{TemplateBinding Background}">
<ContentPresenter x:Name="contentPresenter" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsDefaulted" Value="true">
<Setter Property="BorderBrush" TargetName="border" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Background" TargetName="innerBorder" Value="{StaticResource Button.MouseOver.Background}"/>
<Setter Property="BorderBrush" TargetName="border" Value="{StaticResource Button.MouseOver.Border}"/>
</Trigger>
<Trigger Property="IsPressed" Value="true">
<Setter Property="Background" TargetName="innerBorder" Value="{StaticResource Button.Pressed.Background}"/>
<Setter Property="BorderBrush" TargetName="border" Value="{StaticResource Button.Pressed.Border}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Background" TargetName="innerBorder" Value="{StaticResource Button.Disabled.Background}"/>
<Setter Property="BorderBrush" TargetName="border" Value="{StaticResource Button.Disabled.Border}"/>
<Setter Property="TextElement.Foreground" TargetName="contentPresenter" Value="{StaticResource Button.Disabled.Foreground}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
If you put these style in a resource dictionary in scope, you can use it like this.
<Button Grid.Column="3" Style="{StaticResource ButtonStyle}" Padding="20, 0">
<Button.Background>
<ImageBrush Stretch="Fill" TileMode="None">
<ImageBrush.ImageSource>
<DrawingImage Drawing="{StaticResource MyImage}" />
</ImageBrush.ImageSource>
</ImageBrush>
</Button.Background>
</Button>
Of course, if you omit the style key, you could also make it implicit, if you want.
The problem:
I would like to create a button template in XAML where I bind the image source to a content presenter content box or anything similar.
Required parameters for the solution:
I understand that for a standard button I'm able to add a stackpanel or grid to the button, insert an image into said container and call it a day. However, I'm not a fan of the windows 'chrome' look nor the blue mouse over, click, and focus effects. What I'm attempting to do is create a new button template (editing a copy of the default button template and removing the chrome container) that has the capability to be a base template with the option of changing images as I add more buttons.
Things I've tried and their results:
<Button x:Name="btn">
<StackPanel>
<Image source="imgsource.png"/>
</StackPanel>
</Button>
Result: Has the button chrome effect. Can be a fall back if nothing else possible but I don't like it.
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="bContainer" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" Height="{TemplateBinding Height}" VerticalAlignment="{TemplateBinding VerticalAlignment}" Width="{TemplateBinding Width}">
<Grid x:Name="gBody" Background="#FF3C3C3C"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsKeyboardFocused" Value="true"/>
<Trigger Property="ToggleButton.IsChecked" Value="true"/>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="#ADADAD"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Button Style="{DynamicResource ButtonStyle}">
<Grid>
<Image Source="imgsource.png"/>
</Grid>
</Button>
Result: The image doesn't show up. I'm thinking this is due to the button custom template, but my knowledge on this is limited so I haven't delved too deep.
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="bContainer" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" Height="{TemplateBinding Height}" VerticalAlignment="{TemplateBinding VerticalAlignment}" Width="{TemplateBinding Width}">
<Image x:Name="iImage" Source="{Binding Content, RelativeSource={RelativeSource TemplatedParent}}" HorizontalAlignment="Left" Height="16" VerticalAlignment="Top" Width="16"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsKeyboardFocused" Value="true"/>
<Trigger Property="ToggleButton.IsChecked" Value="true"/>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="#ADADAD"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Button Style="{DynamicResource ButtonStyle}">
<Grid>
<Image Source="imgsource.png"/>
</Grid>
</Button>
Result: The image only shows up when entering the FULL path to the image. I'm not sure if I'm correct, but wouldn't this cause problems when deploying the program?
I'm kind of surprised your third example works - even with the full path. Just at a glance it does not seem like it should work. Your second attempt is close but you do not have a site to bind the button's content to.
Look at your button:
<Button Style="{DynamicResource ButtonStyle}">
<Grid>
<Image Source="imgsource.png"/>
</Grid>
</Button>
The Grid is the Content (the grid is not necessary - you can just put the Image there). Looking at your template you can see there is nothing in there that will pick up the content. Try adding a content presenter to your template:
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="bContainer"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
Height="{TemplateBinding Height}"
VerticalAlignment="{TemplateBinding VerticalAlignment}"
Width="{TemplateBinding Width}">
<ContentPresenter x:Name="contentPresenter"
Focusable="False"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}"
RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsKeyboardFocused"
Value="true"/>
<Trigger Property="ToggleButton.IsChecked"
Value="true"/>
<Trigger Property="IsEnabled"
Value="false">
<Setter Property="Foreground"
Value="#ADADAD"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
I have following Button in my c#WPF 3.5 .NET Application
<Button Height="23" x:Name="btnImportKvf" Width="75" Click="btnImportKvf_Click" IsEnabled="True" ToolTip="Click to Import" Content="Import KVF" />
My button style template applied in ResourceDirectory App.xaml as following
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Luna">
<!-- Focus Visual -->
<Style x:Key="ButtonFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Border>
<Rectangle
Margin="2"
StrokeThickness="1"
Stroke="#60000000"
StrokeDashArray="1 2"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- SimpleStyles: Button -->
<Style TargetType="Button">
<!--Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/-->
<Setter Property="Foreground" Value="{StaticResource GlyphLightBrush}"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="border" Background="{DynamicResource BackgroundNormal}" BorderThickness="1,1,1,2" CornerRadius="4,4,4,4" BorderBrush="{DynamicResource GlyphDarkBrush}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="0.507*"/>
<RowDefinition Height="0.493*"/>
</Grid.RowDefinitions>
<Border Opacity="0" HorizontalAlignment="Stretch" x:Name="glow" Width="Auto" Grid.RowSpan="2" CornerRadius="4,4,4,4" Background="{StaticResource GlowBrush}" />
<!--ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Width="Auto" Grid.RowSpan="2"/-->
<ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" RecognizesAccessKey="True" Grid.RowSpan="2"/>
<Border HorizontalAlignment="Stretch" Margin="0,0,0,0" x:Name="shine" Width="Auto" CornerRadius="4,4,0,0" Background="{DynamicResource ShineBrush}"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" TargetName="border" Value="{DynamicResource DisabledForegroundBrush}"/>
</Trigger>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Background" TargetName="border" Value="{DynamicResource GlowBrush}"/>
</Trigger>
<!--Trigger Property="LostFocus">
<Setter Property="Background" TargetName="border" Value="{DynamicResource BackgroundNormal}"/>
</Trigger-->
<Trigger Property="IsPressed" Value="True">
<Setter Property="Opacity" TargetName="shine" Value="0.4"/>
<Setter Property="Visibility" TargetName="glow" Value="Hidden"/>
<Setter Property="Background" TargetName="border" Value="{DynamicResource GlowBrush}"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="{StaticResource GlyphDarkBrush}" />
<Setter Property="Background" TargetName="border" Value="{DynamicResource GlowBrush}"/>
</Trigger>
<Trigger Property="IsCancel" Value="False"/>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFFFFFFF" Offset="0"/>
<GradientStop Color="#FFEAEBF0" Offset="0.9"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
Now I am doing localization in my project, so while changes language like french, then Button text would become big rather than button width, so I want auto texttrimming in button style. and full text display in tooltip.
Also i have second kind of button with Images and Text as following.
<Button Name="btnRefresh" Click="btnRefresh_Click" Width="69" ToolTipService.ToolTip="Click To Refresh" FontSize="11" Content="Refresh">
<Image Source="../Images/Refresh.png" Width="18" Height="13" />
</Button>
I also want to apply same style with this button too.
So is it possible to do this in same style template?
Please help me to solve this.
Thanks in Advance.
To do this, you need to change the ContentPresenter in your style to a Textblock, and bind its Text to your Content.
If you replace with something along those lines, you should be able to set text trimming as you like.
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="border"
Background="{DynamicResource BackgroundNormal}"
BorderThickness="1,1,1,2"
CornerRadius="4,4,4,4"
BorderBrush="{DynamicResource GlyphDarkBrush}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="0.507*"/>
<RowDefinition Height="0.493*"/>
</Grid.RowDefinitions>
<Border Opacity="0"
HorizontalAlignment="Stretch"
x:Name="glow"
Width="Auto"
Grid.RowSpan="2"
CornerRadius="4,4,4,4"
Background="{StaticResource GlowBrush}" />
<TextBlock Text="{TemplateBinding Content}"
TextTrimming="WordEllipsis"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Grid.RowSpan="2"/>
<Border HorizontalAlignment="Stretch"
Margin="0,0,0,0"
x:Name="shine"
Width="Auto"
CornerRadius="4,4,0,0"
Background="{DynamicResource ShineBrush}"/>
</Grid>
</Border>
...
</ControlTemplate>
EDIT: regarding the second part of your question.
The last piece of code you show cannot work as you're setting the Content of your Button twice (I don't think it actually compiles).
The cleanest way of doing what you're trying to achieve is to define a custom Control class, as described here.
A "not so clean" hack could be to use the Tag field of your Button to store the image source URI like this:
<Button Name="btnRefresh"
Click="btnRefresh_Click"
Width="69"
ToolTipService.ToolTip="Click To Refresh"
FontSize="11" Content="Refresh"
Tag="../Images/Refresh.png" Width="18" Height="13" />
And then retrieve it in your style. This Grid replaces the Textblock in the previous solution:
<Grid Grid.RowSpan="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Grid.Column="0"
Source="{Binding RelativeSource={RelativeSource TemplatedParent},Path=Tag}" />
<TextBlock Text="{TemplateBinding Content}"
Grid.Column="1"
TextTrimming="WordEllipsis"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Grid>
The reason why the binding is slightly different is explained here.
But again, creating a custom Button with image and text is probably the cleanest way to do this!
I've created style for button in my WPF app:
<Style x:Key="buttonStyle" TargetType="Button">
<Setter Property="Border.BorderBrush" Value="Black" />
<Setter Property="Border.BorderThickness" Value="1" />
<Setter Property="Border.Background" Value="White" />
<Setter Property="Height" Value="25" />
<Setter Property="Width" Value="100" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border
Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ContentPresenter
HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Red" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Then I'm putting this style to Button control:
<Button Style="{StaticResource buttonStyle}" Grid.Row="1" Grid.Column="1" Content="Press"/>
When I'm running my app, I see grey shadow under and right of the button. Futhermore when I look in Visual Studio view I don't see shadow. How can I delete this effect? Anyone an idea or an completly other approach?
Are you sure what you're seeing is actually a shadow? It could simply be a blurred edge. WPF's layout system is based on device-independent pixels, so it's possible for an element's edge to reside between two device pixels, in which case it may appear blurred.
You can force device-pixel snapping by setting UseLayoutRounding="True" on a parent element in WPF 4.0 and later; in earlier versions, you can try SnapsToDevicePixels="True".
I am trying to make a simple mouseover effect on a button, It does change the color when mouse is over but the color is immediately changed to the default button background... how can I override this behavior?
this is my code:
Style myBtnStyle = new Style();
Trigger bla = new Trigger() { Property = IsMouseOverProperty, Value = true };
bla.Setters.Add(new Setter(Control.BackgroundProperty, Brushes.Black));
myBtnStyle.Triggers.Add(bla);
button2.Style = myBtnStyle;
According to this post, that fancy animation is built into and to remove it, you're going to need to override the ControlTemplate for your Button. Fortunately, that isn't too hard. I used this post as source material and came up with the following Style that gives you the idea.
<Style x:Key="MouseOverButtonStyle" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<ControlTemplate.Resources>
<Style x:Key="ShadowStyle">
<Setter Property="Control.Foreground" Value="LightGray" />
</Style>
</ControlTemplate.Resources>
<Border Name="border" BorderThickness="1" Padding="4,2" BorderBrush="DarkGray" CornerRadius="3" Background="{TemplateBinding Background}">
<Grid >
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Name="contentShadow" Style="{StaticResource ShadowStyle}">
<ContentPresenter.RenderTransform>
<TranslateTransform X="1.0" Y="1.0" />
</ContentPresenter.RenderTransform>
</ContentPresenter>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Name="content"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Beige" />
</Trigger>
</Style.Triggers>
</Style>
Update:
If you're dead set on applying the Style in code and you don't want to use a ResourceDictionary (probably the better way to do it), you can load the Style dynamically using XamlReader.Load:
const string xaml = #"
<Style xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
TargetType='Button'>
<Setter Property='Template'>
<!--- Omitted For Clarity --->
</Setter>
<Style.Triggers>
<Trigger Property='IsMouseOver' Value='True'>
<Setter Property='Background' Value='Beige' />
</Trigger>
</Style.Triggers>
</Style>";
var encoding = new ASCIIEncoding();
var bytes = encoding.GetBytes(xaml);
var style = (Style)XamlReader.Load(new MemoryStream(bytes));
Button1.Style = style;
Overriding the ButtonChrome theme would be easier.
Create a template and remove the RenderMouseOver="{TemplateBinding IsMouseOver}"
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Microsoft_Windows_Themes:ButtonChrome x:Name="Chrome" BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" RenderMouseOver="{TemplateBinding IsMouseOver}"RenderPressed="{TemplateBinding IsPressed}" RenderDefaulted="{TemplateBinding Button.IsDefaulted}" SnapsToDevicePixels="True">
<ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Microsoft_Windows_Themes:ButtonChrome>
<ControlTemplate.Triggers>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter Property="RenderDefaulted" TargetName="Chrome" Value="True"/>
</Trigger>
<Trigger Property="ToggleButton.IsChecked" Value="True">
<Setter Property="RenderPressed" TargetName="Chrome" Value="True"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="#FFADADAD"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
And then add your own handling of mouseover
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFF3E8D5" Offset="0"/>
<GradientStop Color="#FFF49B03" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
That should solve it! :)