Having an issue with my TextBox control template - c#

I am working on a simple textBox template, which is just two borders, one with a gradient background. Now, my specific issue is that I want to be able to set the foreground color of the textBox to whatever color I want and have it work correctly. However, I can't seem to get both the disabled foreground and enabled foreground colors to work together. If I set the foreground to red for example, when I disable the textBox, the foreground doesn't get changed to my disabled color. I tried binding the foreground in the IsEnabled="true" trigger but that doesn't seem to work. The foreground always stays red, no matter if the textBox is enabled or not.
Can you please take a look at the below template and tell me what I am doing wrong? Also, please point out to me any other mistakes I may have made since I am new at creating templates.
Thanks a lot.
<SolidColorBrush x:Key="DisabledForegroundBrush" Color="#888" />
<SolidColorBrush x:Key="DisabledBackgroundBrush" Color="#EEE" />
<SolidColorBrush x:Key="WindowBackgroundBrush" Color="#FFF" />
<SolidColorBrush x:Key="SelectedBackgroundBrush" Color="#DDD" />
<Style x:Key="TextBoxControlTemplate1" TargetType="{x:Type TextBox}">
<Setter Property="KeyboardNavigation.TabNavigation" Value="None"/>
<Setter Property="AllowDrop" Value="true"/>
<Setter Property="Background" Value="#00000000"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="FontFamily" Value="Segoe UI"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="Padding" Value="8,5,3,3"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Grid>
<Border BorderBrush="#FF000000" BorderThickness="2,2,2,2" CornerRadius="5,5,5,5" Padding="0,0,0,0" Width="Auto" Height="Auto" Background="#FF000000"/>
<Border x:Name="Border" BorderBrush="#FFFFFFFF" BorderThickness="1,1,1,1" CornerRadius="5,5,5,5" Padding="0,0,0,0" Width="Auto" Height="Auto" Margin="2,2,2,2">
<Border.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF000000" Offset="0"/>
<GradientStop Color="#FF4D4D4D" Offset="1"/>
</LinearGradientBrush>
</Border.Background>
</Border>
<ScrollViewer Margin="0" x:Name="PART_ContentHost"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" Value="{DynamicResource DisabledBackgroundBrush}" TargetName="Border"/>
<Setter Property="BorderBrush" Value="{DynamicResource DisabledBackgroundBrush}" TargetName="Border"/>
<Setter Property="Foreground" Value="{DynamicResource DisabledForegroundBrush}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="True">
<Setter Property="Foreground" Value="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type TextBox}}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<TextBox Text="TEST" TextWrapping="Wrap" Canvas.Top="293.761" Canvas.Left="112" Style="{DynamicResource TextBoxControlTemplate1}" Height="28.724" Width="232.25" IsTabStop="False" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" HorizontalContentAlignment="Right" VerticalContentAlignment="Center" IsEnabled="True" Foreground="#FFFF0000"/>

There are a few different issues here all working against you. The first is that you're setting a specific Foreground value on your control instance, which has a higher priority than values set from Triggers in your Style for properties of the control itself. This is different than properties set on elements inside the ControlTemplate, like "Border". The way you're using Triggers to set the Border properties is illustrating that. Normally you would also want to use TemplateBindings to pull in values set on your control instance as defaults, like Background, which are currently being ignored.
To switch between two values of a property on your styled control, like you want to do with Foreground, you can use a Setter and a Trigger in your Style to provide a default and alternate value. This is still subject to being overridden by a value set on an instance. If you want to disallow instances overriding a Trigger set it up like the "Border" Trigger where you're setting values on elements inside the ControlTemplate.
The last change I'd recommend is switching to StaticResource for the Brushes you're pulling into your Style. In this case it probably won't make a difference, but in some cases a default Style can get pulled into a context that doesn't have any reference to the surrounding Resources from the file it was declared in. Using Static will guarantee that it will include those Resources no matter where it gets used. You may not run into this but it's a good habit to get into when setting up Styles/Templates like this.
Here's your code with those improvements:
<SolidColorBrush x:Key="DisabledForegroundBrush" Color="#888" />
<SolidColorBrush x:Key="DisabledBackgroundBrush" Color="#EEE" />
<Style x:Key="TextBoxControlTemplate1" TargetType="{x:Type TextBox}">
<Setter Property="KeyboardNavigation.TabNavigation" Value="None"/>
<Setter Property="AllowDrop" Value="true"/>
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF000000" Offset="0"/>
<GradientStop Color="#FF4D4D4D" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="FontFamily" Value="Segoe UI"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="Padding" Value="8,5,3,3"/>
<Setter Property="BorderThickness" Value="2"/>
<Setter Property="BorderBrush" Value="#FF000000"/>
<Setter Property="Foreground" Value="Red" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Grid>
<!--Take advantage of containment when possible to let the layout engine help you!-->
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="5" Padding="0" Background="#FF000000"/>
<Border x:Name="Border" BorderBrush="#FFFFFFFF" BorderThickness="1" CornerRadius="5" Padding="0" Margin="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"/>
<ScrollViewer Margin="0" x:Name="PART_ContentHost"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" Value="{StaticResource DisabledBackgroundBrush}" TargetName="Border"/>
<Setter Property="BorderBrush" Value="{StaticResource DisabledBackgroundBrush}" TargetName="Border"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="{StaticResource DisabledForegroundBrush}"/>
</Trigger>
</Style.Triggers>
</Style>
And the TextBox using only the Style settings:
<TextBox Text="TEST" TextWrapping="Wrap" Canvas.Top="293.761" Canvas.Left="112" Style="{DynamicResource TextBoxControlTemplate1}"
Height="28.724" Width="232.25" IsTabStop="False" HorizontalContentAlignment="Right" VerticalContentAlignment="Center" />

A couple ideas to try:
Get rid of one of your triggers. Having two opposing triggers may not be a good idea. I would set the default Background, BorderBrush, and Foreground directly on your Border declaration, and remove the Enabled="True" trigger. Then, debugging is only a matter of getting the Enabled="False" trigger right.
Add the TargetName property to setter for your Enabled="False" trigger.
This is a longshot, but use UIElement.IsEnabled instead of just IsEnabled, like this: <Trigger Property="UIElement.IsEnabled">.
Hope something I've said here helps!

The possible reason is that your DisabledBackgroundBrush is not visible at the point where you use your style. Please try to add the styles into the ControlTemplate's resources:
<ControlTemplate TargetType="{x:Type TextBox}">
<ControlTemplate.Resources>
<SolidColorBrush x:Key="DisabledBackgroundBrush" Color="#EEE" />
...
</ControlTemplate.Resources>
...
By the way, your control template doesn't honour the values of your properties.
For example, you should perhaps use something like
<ScrollViewer Margin="{TemplateBinding Padding}" x:Name="PART_ContentHost"/>
in your control template.

Related

Button Background Margin

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.

WPF DataGrid CellStyle implicit style applied instead of explicit

Defined implicit DataGridCell style is applied instead of the explicit style set via DataGrid's style (DataGrid.CellStyle property). Why? How does the XAML evaluate, whether to use Implicit style over Explicit in this case?
I am trying to create DataGrid style, which will also set the DataGridCells' style.
Tried removing the Implicit DataGridCell style and everything works as expected, explicit style gets working properly.
How to make them work together?
Also providing the DataGridCell style as DataGrid's style resource works. How? Why?
Implicit Style of the DataGridCell
<!-- Implicit DataGridCell style -->
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="FontSize" Value="14" />
<Setter Property="Background" Value="White" />
<Setter Property="BorderBrush" Value="White" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="White" />
<Setter Property="BorderBrush" Value="White" />
</Trigger>
</Style.Triggers>
</Style>
Style of the DataGridCell, which I want to apply
<!-- Explicit DataGridCellStyle -->
<Style x:Key="DataGridCellStyle" TargetType="DataGridCell" BasedOn="{StaticResource {x:Type DataGridCell}}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Border BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Foreground" Value="#ffffff" />
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1"
MappingMode="RelativeToBoundingBox" StartPoint="0.5,0">
<GradientStop Color="#FF3b85c8" Offset="0" />
<GradientStop Color="#FF0668b7" Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
Style of the DataGrid
<!-- DataGrid style -->
<Style x:Key="BaseDataGrid" TargetType="{x:Type DataGrid}">
<Setter Property="CellStyle" Value="{StaticResource DataGridCellStyle}" />
<!-- Uncommenting this makes the solution works even with Implicit style -->
<!--<Style.Resources>
<Style TargetType="{x:Type DataGridCell}" BasedOn="{StaticResource DataGridCellStyle}"/>
</Style.Resources>-->
</Style>
Simple Datagrid instance
<!-- Data grid itself -->
<DataGrid Style="{StaticResource BaseDataGrid}"
AutoGenerateColumns="True"
ItemsSource="{Binding ModelClasses}">
</DataGrid>

WPF Style Trigger with targetname not working as expected

I have an issue setting the Foreground color in a ControlTemplate with triggers.
<LinearGradientBrush x:Key="TabItemDefaultBackgroundBrush" StartPoint="0,0" EndPoint="0,1">
<GradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Offset="0.0" Color="#FFF" />
<GradientStop Offset="1.0" Color="#EEE" />
</GradientStopCollection>
</GradientBrush.GradientStops>
</LinearGradientBrush>
<SolidColorBrush x:Key="SolidBorderBrush" Color="#888" />
<SolidColorBrush x:Key="TabItemSelectBackgroundBrush" Color="#69C" />
<SolidColorBrush x:Key="PressedBrush" Color="#79C" />
<Style TargetType="{x:Type TabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid>
<Border
Name="tabBorder"
MinWidth="150"
MinHeight="50"
Margin="0,0,20,0"
Background="{StaticResource TabItemDefaultBackgroundBrush}"
BorderBrush="{StaticResource SolidBorderBrush}"
BorderThickness="1"
CornerRadius="1,1,1,1">
<Grid>
<Grid >
<TextBlock Name="HeaderHeader">
</TextBlock>
</Grid>
<ContentPresenter
x:Name="ContentSite"
Margin="12,2,12,2"
HorizontalAlignment="Center"
VerticalAlignment="Center"
ContentSource="Header"
RecognizesAccessKey="True" />
</Grid>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="HeaderHeader" Property="Foreground" Value="White" />
<Setter TargetName="tabBorder" Property="Background" Value="{StaticResource TabItemSelectBackgroundBrush}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
When the tab is selected, the background border 'tabBorder' is set correctly, but the foreground of textblock 'HeaderHeader' does not respond.
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="HeaderHeader" Property="Foreground" Value="White" />
<Setter TargetName="tabBorder" Property="Background" Value="{StaticResource TabItemSelectBackgroundBrush}" />
</Trigger>
</ControlTemplate.Triggers>
When I remove the TargetName and set the foreground white (to all components), it does work. (but obviously also the foreground color of everything in the content pre
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="White" />
<Setter TargetName="tabBorder" Property="Background" Value="{StaticResource TabItemSelectBackgroundBrush}" />
</Trigger>
</ControlTemplate.Triggers>
Even stranger, when I put the TargetName back in place, but change the setter property from foreground to background, it DOES work! Then the background is set to white for the selected tab.
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="HeaderHeader" Property="Background" Value="White" />
<Setter TargetName="tabBorder" Property="Background" Value="{StaticResource TabItemSelectBackgroundBrush}" />
</Trigger>
</ControlTemplate.Triggers>
Why on earth is it not working for what I need (=set foreground for selected tab)?!
Aha, I learned something today... I was looking in the wrong direction ! After googling more on "ControlTemplate" something finally sunk in. The ContentPresenter does not show the information of the tab, it shows the label of the tab and nothing more. So my trigger was working just fine, but it was setting the foreground of a textblock which had no meaning at all!
When I change the trigger to which control actually shows the label, it was easy peasy...
<Setter TargetName="ContentSite" Property="TextElement.Foreground" Value="White" />
I did have to use an attached property 'TextElement' in order to be able to set properties on text elements.

Auto hover color for buttons based on their Background color

I've googled a lot but I've found nothing about this situation.
I have several flat Buttons with different Background colors, but the hover color is the same for all of them! I want each Button has its own hover color based on its background, for example gets a little lighter.
I've tried making custom styles and I reduced the Opacity in IsMouseOver trigger, but It's not what I want because it also affects the content of the button and not only the background color!
Win32 C# applications have a Flat Appearance property that do the trick automatically. When you choose a color for the BackColor and set the button as Flat, it takes care of all states color (Hover color, Disabled color, ...), however I've no idea how to do this in WPF.
Thank you in advance
the hover color is the same for all of them!
This is probably because in your Button's style, you have one single Background brush when IsMouseOver is True.
because it also affects the content of the button and not only the background color
This is probably because when the panel (likely a Border) you are animating is also the parent of the content control(e.g. ContentPresenter, ContentControl), so the Opaciy of this content control is also affected.
To solve these problems, you just need to create some visual elements (e.g. Rectangles, Borders) at the same level as your content control, and animate them based on which trigger is activated.
Here is a simple example.
<Window.Resources>
<Style x:Key="FocusVisual">
<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>
<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="#FF737B7F"/>
<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="MyButtonStyle" TargetType="{x:Type Button}">
<Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual}"/>
<Setter Property="Background" Value="{StaticResource Button.Static.Background}"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="4"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid SnapsToDevicePixels="true">
<Rectangle x:Name="BackgroundVisual" Fill="{TemplateBinding Background}"/>
<Rectangle x:Name="PressedVisual" Fill="{DynamicResource Button.Pressed.Background}" Opacity="0"/>
<Rectangle x:Name="DisabledVisual" Fill="{DynamicResource Button.Disabled.Background}" Opacity="0"/>
<ContentPresenter x:Name="contentPresenter" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsDefaulted" Value="true"/>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Opacity" TargetName="BackgroundVisual" Value="0.6"/>
</Trigger>
<Trigger Property="IsPressed" Value="true">
<Setter Property="Opacity" TargetName="PressedVisual" Value="1"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="TextElement.Foreground" TargetName="contentPresenter" Value="{StaticResource Button.Disabled.Foreground}"/>
<Setter Property="Opacity" TargetName="DisabledVisual" Value="1"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="BorderThickness" Value="0"/>
</Style>
</Window.Resources>
Here is how the style looks.
Hope this helps! :)
Check this out :
http://learnwpf.com/post/2006/03/06/How-do-I-change-an-items-appearance-on-mouseover-in-WPF.aspx
for Background you can simply set the "Background" property instead of setting the "BitmapEffect" property.
Hope this helps
Regards

BorderThickness of TextBox in WPF (a bug?)

I have noticed a strange behaviour of TextBox while BorderThickness property is set to 1 - the focus causes the border to change the color (to something like white).
However, if I set the border thickness to something different than 1, say .99 or 1.01 the problem disappears.
Is it the bug in WPF? Or is it intended?
This is the default behavior of the Aero style for TextBoxes. To disable it you would need to restyle the TextBox. You can take the default styles from here (see Download Sample).
In the default Style for TextBoxBase (which TextBox is based on), you will see it uses a ListBoxChrome. This element is defined in the Presentation.Aero assembly and is responsible for rendering the "focused" look. You can simply remove the RenderFocus setting and possibly the RenderMouseOver, or replace it with a Border.
Then you'd want to include that in your application resources.
<LinearGradientBrush x:Key="TextBoxBorder"
StartPoint="0,0" EndPoint="0,20" MappingMode="Absolute">
<LinearGradientBrush.GradientStops>
<GradientStop Color="#ABADB3" Offset="0.05" />
<GradientStop Color="#E2E3EA" Offset="0.07" />
<GradientStop Color="#E3E9EF" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
<Style x:Key="{x:Type TextBoxBase}" TargetType="{x:Type TextBoxBase}" BasedOn="{x:Null}">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" />
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" />
<Setter Property="BorderBrush" Value="{StaticResource TextBoxBorder}" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Padding" Value="1" />
<Setter Property="AllowDrop" Value="true" />
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBoxBase}">
<Border x:Name="Bd" BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}"
SnapsToDevicePixels="true">
<ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Border >
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter TargetName="Bd" Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" />
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBoxBase}}" TargetType="{x:Type TextBox}"/>
If you look at the ListBoxChrome class in Reflector (specifically the OnRender method), you can see it will only render the focused look if it's BorderThickness is "1,1,1,1".

Categories

Resources