Setting RenderTransform in a nested style - wpf

I'm using .Net 3.5 on Windows 8, with the default Aero theme.
This was supposed to be an answer to Scale Checkbox without scaling content but it didn't work as easily as I expected. I'm trying to:
scale the box in a checkbox control
in a style, so I can apply the change to all checkboxes (or only some)
independently of its text, with no need to compensate.
I have a UserControl with this Resources:
<UserControl.Resources>
<ResourceDictionary>
<!-- ... -->
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../Resources/CheckBoxStyle.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
Resources/CheckBoxStyle.xaml is this:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:primitives="clr-namespace:System.Windows.Controls.Primitives;assembly=PresentationFramework">
<Style TargetType="{x:Type CheckBox}">
<Style.Resources>
<Style TargetType="{x:Type BulletDecorator}">
<Setter Property="RenderTransform">
<Setter.Value>
<ScaleTransform ScaleX="2" ScaleY="2"/>
</Setter.Value>
</Setter>
</Style>
</Style.Resources>
</Style>
</ResourceDictionary>
The primitives namespace is in case whatever I settle on needs to know what BulletDecorator is.
I found BulletDecorator in the Aero theme for .Net 3.5 from here, behind the "Default WPF Themes" link, per this answer.
I'm seeing no difference in the size of my checkbox boxes. I don't think I grabbed the wrong element type from the theme, but what else could be happening?
Edit 1:
BulletDecorator contains the checkbox's content anyway, so I tried dropping requirement #3. Now I have a huge box and huge text, and want to shrink the text back down. Here is CheckBoxStyle.xaml:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:primitives="clr-namespace:System.Windows.Controls.Primitives;assembly=PresentationFramework">
<Style TargetType="{x:Type CheckBox}">
<Style.Resources>
<Style TargetType="{x:Type ContentControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ContentControl}">
<ContentPresenter>
<ContentPresenter.LayoutTransform>
<ScaleTransform ScaleX="0.5" ScaleY="0.5" />
</ContentPresenter.LayoutTransform>
</ContentPresenter>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Style.Resources>
<Setter Property="LayoutTransform">
<Setter.Value>
<ScaleTransform ScaleX="2" ScaleY="2"/>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

I found a solution, although it's not perfect. A better answer would still be accepted.
I used Snoopto determine that the element I'm concerned with is already a ContentPresenter. It contains a TextBlock, but for some reason that can't be styled (and it's shown in parentheses in Snoop's hierarchy). Here's my resulting CheckBoxStyle.xaml:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:primitives="clr-namespace:System.Windows.Controls.Primitives;assembly=PresentationFramework">
<Style TargetType="{x:Type CheckBox}">
<Style.Resources>
<Style TargetType="{x:Type ContentPresenter}">
<Setter Property="LayoutTransform">
<Setter.Value>
<ScaleTransform ScaleX="0.5" ScaleY="0.5" />
</Setter.Value>
</Setter>
</Style>
</Style.Resources>
<Setter Property="LayoutTransform">
<Setter.Value>
<ScaleTransform ScaleX="2" ScaleY="2"/>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

Related

Applying default style to all wpf windows

I've got a wpf application that has 20+ windows, most of which serve as dialogs, and I'd like them all to have the same background color.
I've got a typed style for Window defined in a resource dictionary as follows
<Style TargetType="{x:Type Window}">
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Window}">
<Grid Background="{StaticResource WindowBackgroundBrush}">
<AdornerDecorator>
<ContentPresenter/>
</AdornerDecorator>
<ResizeGrip x:Name="WindowResizeGrip" HorizontalAlignment="Right" VerticalAlignment="Bottom" Visibility="Collapsed" IsTabStop="false"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="ResizeMode" Value="CanResizeWithGrip">
<Setter TargetName="WindowResizeGrip" Property="Visibility" Value="Visible"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I've got the dictionary include in the resources for the Application and each Window as follows
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Resources/Resources.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Resources/Resources.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
In Visual Studio, the background brush in the property editor says "Inheritance", but the value says "White". I see the desired background color in Visual Studio, but when I run the application I still see a white background. Can anyone explain what I'm doing wrong here? The WindowBackgroundBrush is getting applied to other controls correctly.
Note if I simplify the Style to be just
<Style TargetType="{x:Type Window}">
<Setter Property="Background" Value="Aqua"/>
</Style>
Visual Studio shows the Background brush as "Style Setter" as the value source and shows the Aqua as the value source, but the window is still white when the app launches.
You did it all correct. Its working at my place ... How are you applying style to window ? I applied as follows..
<Window x:Class="WpfApplicationScratchpad.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplicationScratchpad"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525" Style="{StaticResource Style1}">
here Style1 is your style in resource dictionary. with the name 'Style1'
<Style x:Key="Style1" TargetType="{x:Type Window}">
<Setter Property="WindowStyle" Value="None"/>
<Setter Property="AllowsTransparency" Value="True"/>
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Window}">
<Grid Background="Beige">
<AdornerDecorator>
<ContentPresenter/>
</AdornerDecorator>
<ResizeGrip x:Name="WindowResizeGrip" HorizontalAlignment="Right" VerticalAlignment="Bottom" Visibility="Collapsed" IsTabStop="false"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="ResizeMode" Value="CanResizeWithGrip">
<Setter TargetName="WindowResizeGrip" Property="Visibility" Value="Visible"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Wpf CustomControl why is the style setting not overiding the default

Consider the following really simple CustomControl:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ViewToLearn.WpfControls">
<Style TargetType="{x:Type local:VtlCustomButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:VtlCustomButton}">
<Grid>
<Button Content="Hi" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
And if I add a couple of these to a test project I get the following:
So far so good. Now I decide that in fact I'd prefer to set the background colour of each button to be red. Obviously I could set each button's background property individually;
<Button Content="Hi" Background="Red" />
And that will work. Logic dictates however that if I want all buttons to have a red border then clearly a style would make more sense, so to that end I alter the code of the control like so:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ViewToLearn.WpfControls">
<Style TargetType="{x:Type Button}">
<Setter Property="Background"
Value="Red" />
</Style>
<Style TargetType="{x:Type local:VtlCustomButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:VtlCustomButton}">
<Grid>
<Button Content="Hi" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
However this is having no effect. I'm sure that the principle is correct but applying it to the specifics of a custom control is constantly frustrating me. Why is this as it currently is failing to produce the expected result. Is it because of where I put the style, or something more fundamental that I have failed to grasp?
Edit
I've been trying to get to grips with creating Custom (NOT user) controls and the way to apply styles and templates to them. The control I really want to influence is made up of several different element (buttons, images, panels textboxes etc) but for the sake of this question I opted for a a custom control based on the standard vs template resulting in the code shown above. Using based on definitely hasn't appeared to work, but I did find that the following amendment did work. I'd love to know why this works over my original and what I'm really doing incorrectly in the first place (ie there's probably a more efficient way to go about this especially as there are several elements whose style I'd like to amend).
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ViewToLearn.WpfControls">
<Style x:Key="vtlstyle"
TargetType="{x:Type Button}">
<Setter Property="Background"
Value="Red" />
</Style>
<Style TargetType="{x:Type local:VtlCustomButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:VtlCustomButton}">
<Grid>
<Button Content="Hi"
Style="{StaticResource vtlstyle}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
Use BasedOn:
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="Red" />
</Style>
<Style x:Key="myButtonStyle" TargetType="{x:Type local:VtlCustomButton}" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="Content" Value="Hi"/>
</Style>
EDIT>>>>>
Using the style on a button(out of resources):
<local:VtlCustomButton Style="{StaticResource myButtonStyle}" />

DataGrid styles

vS 2008 with WPF toolkit installed and referenced.
In the Window1.xaml I added this line:
xmlns:my="http://schemas.microsoft.com/wpf/2008/toolkit"
It runs, grid displays with data, until I attempt to style the grid. I get an error when attempting to apply a style that centers the text. The error refers to App.xaml and is:
The type reference cannot find a public type named 'DataGridCell'. Line 9 Position 75.
My App.xaml
<Application x:Class="DataGridStyles.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="Window1.xaml">
<Application.Resources>
<Style x:Key="CenterCellStyle" TargetType="{x:Type DataGridCell}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Grid Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="Foreground" Value="Black" />
</Trigger>
</Style.Triggers>
</Style>
</Application.Resources>
</Application>
If the datagrid is part of the WPF toolkit, you'll need to add that namespace in your App.xaml too (xmlns:my="http://schemas.microsoft.com/wpf/2008/toolkit").
Then, just change your TargetType="{x:Type DataGridCell}" to TargetType="{x:Type my:DataGridCell}"

WPF how to set a tooltip to textbox (in style file)

I wanted to have nice ToolTip for my TextBox, so I started with simple ToolTip:
<TextBox>
<TextBox.ToolTip>
<StackPanel>
<TextBlock>Nice text</TextBlock>
<TextBlock>Nice text</TextBlock>
</StackPanel>
</TextBox.ToolTip>
</TextBox>
However I have a dozen TextBoxes and I wanted them all to have the ToolTip above. That's why I decided to transfer the code above into a Style file.
My Style file looks like:
<Style x:Key="DefaultStyle" TargetType="{x:Type TextBox}">
<Setter Property="FontFamily" Value="Tahoma"/>
<Setter Property="FontSize" Value="15"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="TextAlignment" Value="Center"/>
<Setter Property="TextWrapping" Value="Wrap"/>
<Setter Property="BorderBrush" Value="#A9C2DE"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1" >
<GradientStop Color="#CDE1F7" Offset="0.01"/>
<GradientStop Color="#DFECFA" Offset="0.8" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="ToolTip">
<Setter.Value>
<StackPanel>
<TextBlock Text="Nice toolbox"/>
<TextBlock Text="Nice tooltip"/>
</StackPanel>
</Setter.Value>
</Setter>
</Style>
However now I get error XAML parse exception.
How can I set this kind of ToolTip (with StackPanels etc) to TextBox (from style file)??
Dotnet Version < 4
The style looks good but there seems to be an issue with specifing the tooltip directly in the styles value. Declare the ToolTip as a resource and then set it in the style via StaticResource.
<ToolTip x:Key="YourToolTip" >
<StackPanel>
<TextBlock Text="Nice toolbox"/>
<TextBlock Text="Nice tooltip"/>
</StackPanel>
</ToolTip>
... Your Style...
<Setter Property="TextBox.ToolTip" Value="{StaticResource YourToolTip}"/>
...
Dotnet Version == 4
If you work with .net4, it's something other. You wrote that you put it into a style file. Do you mean a resource-file? If yes, may be you have not loaded it during runtime. Something like:
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/YourStyleFile.xaml"/>
<ResourceDictionary>
<!-- Other local resources -->
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
Another possibility is that you try to use it on another type than TextBox. This does not work because you declared TextBox as target type.

Silverlight 4 and Page.Resources Binding

In my SL4 application, I have a Class called Images which has two properties (ImagePath, ImageName) and a method getImages() which retruns ObservableCollection list of all Images.
I need to create a Resource on my Page so that when a DataTemplate is loaded dynamically it can have access to the Images in one of its ComboBox field.
How can I do that?
<Page.Resources>
<local:Images x:Key="MyImages"/>
</Page.Resources>
But in my code behind file I cannot access the MyImages
You have 3 options
1. Use global app resource file.
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Assets/StylesA.xaml"/>
<ResourceDictionary Source="Assets/StylesB.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
And within StylesA.xaml just put style you have to use
<StackPanel>
<StackPanel.Resources>
<Style x:Key="HeaderStyle" TargetType="TextBlock">
<Setter Property="FontWeight" Value="Bold"></Setter>
<Setter Property="FontSize" Value="12"></Setter>
</Style>
</StackPanel.Resources>
<TextBlock Style="{StaticResource HeaderStyle}"></TextBlock> ....
2. Use local control Resources section.
<StackPanel>
<StackPanel.Resources>
<Style x:Key="HeaderStyle" TargetType="TextBlock">
<Setter Property="FontWeight" Value="Bold"></Setter>
<Setter Property="FontSize" Value="12"></Setter>
</Style>
</StackPanel.Resources>
<TextBlock Style="{StaticResource HeaderStyle}"></TextBlock> ....
3. Just use Page.Resources within your page
<navigation:Page.Resources>
<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>
</navigation:Page.Resources>
I hope it will help. :)

Resources