I have a UserControl with some buttons. My button have the default FocusVisualStyle (the border around the button).
When I move my user control with the mouse, this dotted border does not move with it. When you hover over another part of the screen it moves into the correct position.
I don't want to set the FocusVisualStyle to null, because I need to see what element is focused. I tried to create my own FocusVisualStyle but it behaves like the default one.
Can I somehow synchronize this border with the rest of the elements?
Thanks for help
As stated by bitbonk, the RenderTransform does not cause another arrange pass so the focus visual will not move. You can read this Dr. WPF article which discusses the issue as well as providing a couple of workarounds. The easiest in your case is to just put an AdornerDecorator within your UserControl around the content of your UserControl so that the AdornerLayer is moved too.
When you use RenderTransform the FocusVisualStyle rectangle is not moved with the button because it is rendered in the layout pass. That is the whole point of the RenderTransform: transform any visual and ignore the layout of the rest of the visual tree.
You will have to use LayoutTransform, or Button.Margin or Canvas.Left, Canvas.Top to move your button.
This (somewhat cryptic) excerpt from the MSDN speaks to the more general form of this issue:
Focus visual styles act exclusively for keyboard focus. As such, focus visual styles are a type of accessibility feature. If you want UI changes for any type of focus, whether via mouse, keyboard, or programmatically, then you should not use focus visual styles, and should instead use setters and triggers in styles or templates that are working from the value of general focus properties such as IsFocused or IsFocusWithin.
Today, that last bit about using triggers would probably be better replaced with a suggestion that you use the Visual State Manager. Here's some XAML that does it that way, but also preserves the original setting for a Button's FocusVisualStyle. That setting draws a dashed rectangle two pixels inside a Button when it receives focus from the keyboard. My Storyboards for the Focused and Unfocused visual states add and remove a solid rectangle, four pixels inside a Button, whenever it gains or loses the focus for any reason.
If you create a pair of Buttons in a WPF Window and manipulate the focus by keyboard and by mouse, clicking those Buttons with the spacebar and the mouse, you'll see that a Button often has the focus when the FocusVisualStyle doesn't appear. Again, this (according to the excerpt above) is by design. (I'm puzzled as to how this is an "accessibility feature," as it can easily neglect to show which control will be clicked the next time the spacebar is pressed. My inclination is just not to use it at all.)
NOTE: The code below is for a custom control derived from Button, called "XLButton." You can change the Style's TargetType to Button if you don't want to create a custom control to try this.
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ExLuminaControls">
<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.Border" Color="#FF707070"/>
<Style TargetType="{x:Type local:XLButton}">
<Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual}"/>
<Setter Property="BorderBrush" Value="{StaticResource Button.Static.Border}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="{x:Null}"/>
<Setter Property="Padding" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:XLButton}">
<Grid>
<Border x:Name="border"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
SnapsToDevicePixels="true"/>
<Rectangle x:Name ="glow" Fill="White" Opacity="0"/>
<Rectangle x:Name="shade" Fill="Black" Opacity="0"/>
<ContentPresenter x:Name="contentPresenter"
Focusable="False"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}"
RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
<Rectangle x:Name="dis" Fill="Gray" Opacity="0"/>
<Rectangle x:Name="foc" Margin="4" SnapsToDevicePixels="true"
Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"
StrokeThickness="1" Opacity="0"/>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="CommonStates">
<VisualState Name="Normal">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="glow"
Storyboard.TargetProperty="Opacity"
To="0" Duration="0:0:.1"/>
</Storyboard>
</VisualState>
<VisualState Name="MouseOver">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="glow"
Storyboard.TargetProperty="Opacity"
To=".25" Duration="0:0:.1"/>
</Storyboard>
</VisualState>
<VisualState Name="Pressed">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="shade"
Storyboard.TargetProperty="Opacity"
To=".25" Duration="0:0:0"/>
</Storyboard>
</VisualState>
<VisualState Name="Disabled">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="dis"
Storyboard.TargetProperty="Opacity"
To=".25" Duration="0:0:0"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup Name="FocusStates">
<VisualState Name="Focused">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="foc"
Storyboard.TargetProperty="Opacity"
To="1" Duration="0:0:.1"/>
</Storyboard>
</VisualState>
<VisualState Name="Unfocused">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="foc"
Storyboard.TargetProperty="Opacity"
To="0" Duration="0:0:.1"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
Related
I have ListBox:
<ListBox x:Name="ListBoxImages"
ScrollViewer.CanContentScroll="True"
UseLayoutRounding="False"
SelectionMode="Extended"/>
ListBox style:
<Style TargetType="{x:Type ListBox}">
...
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBox">
<Border Name="Border">
<ScrollViewer Focusable="false">
<WrapPanel ItemWidth="100"
IsItemsHost="True"/>
</ScrollViewer>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
and ListBoxItem style (animation here, sorry for long code):
<Style TargetType="{x:Type ListBoxItem}">
<!--...-->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border x:Name="border"
RenderTransformOrigin="0.5,0.5">
<Border.RenderTransform>
<TransformGroup>
<ScaleTransform x:Name="ScaleTransform"/>
</TransformGroup>
</Border.RenderTransform>
<ContentPresenter/>
</Border>
<!--Animation-->
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="ScaleTransform"
Storyboard.TargetProperty="ScaleX"
Duration="0:0:0.1"
From="0" To="1"/>
<DoubleAnimation Storyboard.TargetName="ScaleTransform"
Storyboard.TargetProperty="ScaleY"
Duration="0:0:0.1"
From="0" To="1"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="FrameworkElement.Unloaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="ScaleTransform"
Storyboard.TargetProperty="ScaleX"
Duration="0:0:0.1"
To="0"/>
<DoubleAnimation Storyboard.TargetName="ScaleTransform"
Storyboard.TargetProperty="ScaleY"
Duration="0:0:0.1"
To="0"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Question. Animations when adding the element (FrameworkElement.Loaded) played not always. Such feeling that it is played when an item has been created, but not yet displayed.
The animation when item is deleted (FrameworkElement.Unloaded) does not play.
So, how to fix it?
Your Loaded storyboard is defined correctly, thus there should be other reasons why it is sometimes played correctly and sometimes not. Is there a long-living operation on the UI thread when a new item is added to the list box? This would result in a freeze so that the animation is not played fluently all the time.
Your Unloaded storyboard is not played because this event is raised when the element is removed from the visual / logical tree that is used to render the whole scene. This storyboard should be started before this removal but unfortunately there is no mechanism / event that tells that an item is to be removed.
Currently there is no easy way to fade out an item from an ItemsControl in WPF. In WinRT and Silverlight, there are two separate visual states for ItemsControl items that you can use for fade-in or fade-out. As Krishna mentioned, the only way is to implement custom functionality to tell an item that it is about to be removed and that it should run the fade-out animation. After that animation, the item can be removed from the visual / logical tree.
I am trying to use the VisualStateManager inside my ControlTemplate for a ToggleButton. I want the ToggleButton to look one way when checked and another when unchecked. I also want the ToggleButton to look different when it's disabled. The issue I'm having is the Unchecked VisualState seems to be trumping the Disabled VisualState.
The documentation states that "Each VisualStateGroup contains a collection of VisualState objects that are mutually exclusive." That's nice, but what about mutual exclusivity between groups?
Anyhow, here's my ControlTemplate. How can I get the TextBlock to use different color for each of the three states; Checked, Unchecked and Disabled?
<Style x:Key="GraphToggleButtonStyle" TargetType="{x:Type ToggleButton}">
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Cursor" Value="Hand" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border Background="Transparent">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Disabled">
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="TextBlock" To="Pink" Duration="0" />
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="CheckStates">
<VisualState x:Name="Checked">
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="TextBlock" To="#3AA5DB" Duration="0" />
</Storyboard>
</VisualState>
<VisualState x:Name="Unchecked">
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="TextBlock" To="Green" Duration="0" />
</Storyboard>
</VisualState>
<VisualState x:Name="Indeterminate" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="Border" CornerRadius="4" Background="{TemplateBinding Background}">
<StackPanel>
<TextBlock Name="TextBlock" FontFamily="/Resources/#Entypo" Text="🔆" FontSize="87" Foreground="#909090" HorizontalAlignment="Center" Margin="0,-25,0,0" />
<TextBlock FontFamily="Proxima Nova Rg" Text="Stimulator" FontSize="18" Foreground="{StaticResource BlackBrush}" HorizontalAlignment="Center" Margin="0,12,0,0" />
</StackPanel>
</Border>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Each VisualStateGroup contains a collection of VisualState objects that are mutually exclusive
This is actually true. However there is still one more requirement, that's each VisualState should not affect the same properties. In this case your Unchecked state and Disabled state affect the same property Foreground of the same element.
So I don't think we can have any elegant solution for this. We just have this work-around (this is in fact used commonly when styling element in WPF). We need some fake element called DisabledTextBlock, this should be placed in the same Grid with the original element TextBlock. Once the Disabled state comes, that fake element should be shown and hide the original one as well as hide all the effect of the Unchecked (or Checked) state and bring the effect of Disabled to the front. Here is the working code:
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border Background="Transparent">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CheckStates">
<!-- unchanged -->
</VisualStateGroup>
<VisualStateGroup x:Name="CommonStates">
<VisualState Name="Disabled">
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity"
Storyboard.TargetName="DisabledTextBlock" To="1" Duration="0" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="Border" CornerRadius="4" Background="{TemplateBinding Background}">
<StackPanel>
<Grid>
<TextBlock Name="TextBlock" FontFamily="/Resources/#Entypo" Text="🔆"
FontSize="87" Foreground="#909090" HorizontalAlignment="Center"
Margin="0,-25,0,0" Background="Transparent"/>
<!-- the fake element -->
<TextBlock Name="DisabledTextBlock" Opacity="0"
FontFamily="{Binding FontFamily, ElementName=TextBlock}"
Text="{Binding Text,ElementName=TextBlock}"
FontSize="{Binding FontSize,ElementName=TextBlock}"
Foreground="Pink" HorizontalAlignment="Center"
Margin="{Binding Margin, ElementName=TextBlock}"
Background="Transparent"
FontStyle="{Binding FontStyle,ElementName=TextBlock}"
FontWeight="{Binding FontSize, ElementName=TextBlock}"/>
</Grid>
<TextBlock FontFamily="Proxima Nova Rg" Text="Stimulator" FontSize="18"
Foreground="Black" HorizontalAlignment="Center" Margin="0,12,0,0"/>
</StackPanel>
</Border>
</Border>
</ControlTemplate>
You may have some new requirement, however the idea here is clear. That's the only work-around I think.
I'm really surprised that this question does not appear to have been asked yet... if it has, but I just couldn't find it, apologies.
Ok, so my work computer has just been upgraded from Windows 7 to Windows 8. To my absolute horror, my WPF Application looks different in several ways... by different, I mean worse, uglier, controls not lined up correctly, etc. Here is an example:
Windows 7:
Windows 8:
Windows 8 problems (just from this image):
Wrong title bar including buttons (Minimise, Close, etc.)
Wrong size Font in title bar
Wrong FontWeight in headings (Windows 7 SemiBold setting = Windows 8 Bold setting)
Icon (or text) misaligned in title bar
Icon in title bar is very blurry
Wrong Padding and/or Margin settings spacing out items on left
Wrong Padding and/or Margin settings reducing Textbox Heights on right
'Hidden' default selection colour on items on left no longer hidden
Back to front Checkbox tick
Images on some Buttons are very blurry
So, my question is this:
Why do WPF Applications look different between Windows 7 and Windows 8 and can this be fixed?
To clarify this, I'm not after a list of differences between WPF on the two operating systems. I'm also not after fixes for the individual points listed above. I would like for someone to explain why these UIs look different, eg. what is causing these differences. I have also heard talk of some system settings in WPF that would enable me to make the PC render the application as if it were on Windows 7, but I don't know how truthful that was.
UPDATE >>>
As #AndrasSebö kindly pointed out, there is a StackOverflow question named Windows 7 theme for WPF?, which fixes a similar problem for Windows XP. Unfortunately, it doesn't seem to have any effect on Windows 8. Are there any Microsoft users out there that actually know what differences were implemented to cause this problem? Or anyone?
UPDATE 2 >>>
Ok, so after some more testing, I'm beginning to think that this problem is not related to the Windows Theme. Using the code provided in #Gusdor's answer, I tried changing the theme to Aero and there was no visible difference... that got me thinking. I then changed it to Luna to test that code and it worked.
By 'worked', I mean that the Windows Theme changed, but the UI controls, or more accurately, the incorrect Padding and Margin remained. I then tried changing the Theme to Luna using the XAML method mentioned by #AndrasSebö and the same thing happened... the ScrollBars looked different, so I could see that the Theme had changed, but the problem remained.
So now I'm thinking that this might have something to do with the fact that this is a brand new computer that I'm working on... might there be some dll or setting that I need to install? I'm really just guessing here - I have the whole Microsoft .NET Framework installed to version 4.5.1 as I'm on Windows 8.1.
This is an absolute nightmare as I don't have time to go and fix every view in this large application. Please help if you can.
Ok, so unfortunately, there was no quick fix for this problem. If you are in a similar situation and the answers supplied here do not work for you either, then here is a summary of the changes that I manually needed to make in order to make the UI on Windows 8 appear the same as the UI on Windows 7.
TextBox: Needed to add Padding to default Style:
<Setter Property="Padding" Value="1.5,2" />
ListBoxItem: Needed to provide new ControlTemplate to hide selection and mouse over background colours:
<Style x:Key="DefaultListBoxItem" TargetType="{x:Type ListBoxItem}">
<Setter Property="Padding" Value="0" />
<Setter Property="Margin" Value="2,0,1,0" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Top" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="KeyboardNavigation.TabNavigation" Value="Local" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Grid Background="{TemplateBinding Background}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver" />
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="contentPresenter" Storyboard.TargetProperty="Opacity" Duration="0" To=".55" />
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="SelectionStates">
<VisualState x:Name="Unselected" />
<VisualState x:Name="Selected" />
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="FocusVisualElement" Storyboard.TargetProperty="Visibility" Duration="0">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Unfocused"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter x:Name="contentPresenter" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}"/>
<Rectangle x:Name="FocusVisualElement" Fill="{x:Null}" Stroke="{x:Null}" StrokeThickness="0" Visibility="Collapsed" RadiusX="1" RadiusY="1" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
ComboBoxItem: Needed to provide new ControlTemplate to change selection and mouse over background colours:
<Style x:Key="{x:Type ComboBoxItem}" TargetType="{x:Type ComboBoxItem}">
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBoxItem}">
<Border x:Name="Border" Padding="2" SnapsToDevicePixels="true" Background="Transparent">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Border" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0" Value="#FF47484C" /> <!-- Background mouse over colour -->
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Border" Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0" Value="White" /> <!-- Foreground mouse over colour -->
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled" />
</VisualStateGroup>
<VisualStateGroup x:Name="SelectionStates">
<VisualState x:Name="Unselected" />
<VisualState x:Name="Selected">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Border" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0" Value="#FF47484C" /> <!-- Background selection colour -->
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Border" Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0" Value="White" /> <!-- Foreground selection colour -->
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="SelectedUnfocused">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Border" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0" Value="Red" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
CheckBox: Needed to provide new ControlTemplate to stop tick from appearing back to front when Bullet is to the right of the Content (thanks to Fredrik's answer to the Default ControlTemplate for CheckBox question here on Stack Overflow:
<SolidColorBrush x:Key="CheckBoxFillNormal" Color="#F4F4F4" />
<SolidColorBrush x:Key="CheckBoxStroke" Color="#8E8F8F" />
<Style x:Key="EmptyCheckBoxFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Margin="1" SnapsToDevicePixels="true" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="CheckRadioFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Margin="14,0,0,0" SnapsToDevicePixels="true" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="{x:Type CheckBox}" TargetType="{x:Type CheckBox}">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="Background" Value="{StaticResource CheckBoxFillNormal}"/>
<Setter Property="BorderBrush" Value="{StaticResource CheckBoxStroke}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="FocusVisualStyle" Value="{StaticResource EmptyCheckBoxFocusVisual}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type CheckBox}">
<BulletDecorator Background="Transparent" SnapsToDevicePixels="true">
<BulletDecorator.Bullet>
<Aero:BulletChrome BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" IsChecked="{TemplateBinding IsChecked}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderPressed="{TemplateBinding IsPressed}"/>
</BulletDecorator.Bullet>
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</BulletDecorator>
<ControlTemplate.Triggers>
<Trigger Property="HasContent" Value="true">
<Setter Property="FocusVisualStyle" Value="{StaticResource CheckRadioFocusVisual}"/>
<Setter Property="Padding" Value="4,0,0,0"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
To remove the horrendous title bar and display the default Windows 8 one: Needed to upgrade to .NET 4.5 and utilise the included System.Windows.Controls.Ribbon namespace library instead of the separate 'Microsoft Ribbon for WPF' (RibbonControlsLibrary) dll previously used.
Unfortunately, I never found out how to reproduce the SemiBold setting of the FontWeight property on Windows 8. If anyone knows how to do this, please let me know.
On the whole, the move to Windows 8 has been a painful and troubling experience. I hope this information will help others in a slightly less painful manner.
The problem (as described in other answers) is that WPF picks a default theme determined by the operating system version.
You need to override this behavior. THIS ARTICLE describes how:
WPF comes with a few theme assemblies, one for each Windows theme
(Luna, Royale and Aero and the fallback theme, Classic.) Usually the
theme is loaded according to your current system theme, but if you
want to create a consistent look for your application, you may want to
force-load a specific one.
To accomplish that, simply add the following code in your Application
Startup event (this example shows how to use the Aero theme):
Uri uri = new Uri(“PresentationFramework.Aero;V3.0.0.0;31bf3856ad364e35;component\\themes/aero.normalcolor.xaml”, UriKind.Relative);
Resources.MergedDictionaries.Add(Application.LoadComponent(uri) as ResourceDictionary);
It’s important to specify the version and the public key token.
Otherwise you’ll have to copy the theme assembly to the folder of your
executable. The reason I’m adding it to the merged dictionaries
collection is that I don’t want to lose other resources I added to the
App.xaml file.
If you use WPF without custom (explicit) style it is going to use standard windows 7 aero style. In case of windows 8 it is different (aero2).
If you would like to make sure, your application appears same on windows7 and on windows8 as well I recommend to create custom style where you define margin, paddings, fonts, etc by yourself.
Your problem may be related to this
There is currently a bug within the WPF ribbon library, which causes the Windows 8 theme not to apply if a ribbonwindow is being used.
Furthermore Windows 7 and 8 use simply different styles for their Controls such as Textboxes.
When developing for multiple platforms, be it only Windows, you must be aware that sizes, margins and paddings change. Instead of absolute values you should let the controls dictate their need for space by avoiding setting explicit heights or widths altogether.
I have a custom style for Buttons in my Silverlight project and want to set the Foreground (and other properties) of the text in the button. But my idea is to use a ContentPresenter in the style. This way, I can still put whatever I want in the Button.
But if there's text as Content, I want to be able to set certain properties, like Foreground, FontFamily, FontSize, etc. I also want to change these properties on hover, etc.
This is my style (simplified):
<Style x:Key="ButtonStyle" TargetType="Button">
<!-- There are other properties here, but I left them out for brevity -->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="ButtonBorder"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}">
<ContentPresenter x:Name="ButtonContent"
Content="{TemplateBinding Content}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
</ContentPresenter>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<!-- I would like to change the Foreground here -->
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
All information I find, tell me to add TextBlock.Foreground="..." to the ContentPresenter, i.e.:
<ContentPresenter x:Name="ButtonContent"
Content="{TemplateBinding Content}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
TextBlock.Foreground="{TemplateBinding Foreground}">
</ContentPresenter>
However, this doesn't work for me. I get an error saying that the attachable property Foreground isn't available for the type TextBlock. Is this because that solution will only work in WPF, and how can I then set this property in Silverlight?
I know I can just set the Foreground via a <Setter> tag, but then how can I change it on mouse over? I want to set the Foreground of the ContentPresenter, so that in the MouseOver VisualState, I can change it.
(sorry for my bad english)
You can just set the properties on the Button, it should work:
<Button Style="{StaticResource ButtonStyle}" Content="Test" Foreground="Red" FontFamily="Georgia" FontSize="25"/>
Or you can create a style for your text button:
<Style x:Key="ButtonTextStyle" TargetType="Button" BasedOn="{StaticResource ButtonStyle}">
<Setter Property="Foreground" Value="Red"/>
</Style>
and use it:
<Button Style="{StaticResource ButtonTextStyle}" Content="Test"/>
EDIT:
Try to put a ContentControl in the place of the ContentPresenter - So you will have the ForegroundProperty and on you VisualState, inside your StoryBoard:
<ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ButtonContent">
<DiscreteObjectKeyFrame KeyTime="0" Value="Red"/>
</ObjectAnimationUsingKeyFrames>
Have a look at the base line control template used for Button # http://msdn.microsoft.com/en-us/library/cc278069(v=vs.95).aspx, I would recommend you take that control and then adjust the mouse over based on your requirements.
So for you to on mouse over to red, I would do something like the following
<VisualState x:Name="MouseOver">
<Storyboard>
<DoubleAnimation Duration="0" Storyboard.TargetName="BackgroundAnimation" Storyboard.TargetProperty="Opacity" To="1"/>
<ColorAnimation Duration="0" Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)" To="Red"/>
<ColorAnimation Duration="0" Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[2].(GradientStop.Color)" To="Red"/>
<ColorAnimation Duration="0" Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[3].(GradientStop.Color)" To="Red"/>
</Storyboard>
</VisualState>
I have a DataGrid which I am binding to a PagedCollectionView which is grouped and sorted. The contents of the DataGrid are not editable although one column contains a clickable link.
I have restricted the SelectionMode of the DataGrid to DataGridSelectionMode.Single which stops multiple row selection which is good. But the selected row also has a selected Cell which draws in a slightly lighter colour than the rest of the selected row and has a border.
Basically I'd like to have a SelectedRow but not a SelectedCell (from a UI/Display perspective).
It feels like it should be simple matter of setting a property, but I get the feeling maybe I have to edit the DataGrids template and/or mess with the VisualStateManager.
I'm happy to switch to another control other than DataGrid but I do need to be able to display Grouping.
I found 'a' way of making the individual cells appear to be not selected, although I'm not sure if its the best way.
Edit the CellStyle for the DataGrid, Find the Rectangle named FocusVisual. This is the Rectangle thats used to indicate a selected Cell. Set its Fill & Stroke to Transparent, I also set its StrokeThickness to 0. Don't delete the Rectangle entirely because other things are expecting it to be there.
The xaml looked something like this:
<Style x:Key="NonSelectableDataGridCellStyle" TargetType="data:DataGridCell">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="data:DataGridCell">
<Grid x:Name="Root" Background="{TemplateBinding Background}">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CurrentStates">
<VisualState x:Name="Regular"/>
<VisualState x:Name="Current">
<Storyboard>
<DoubleAnimation Duration="0"
Storyboard.TargetName="FocusVisual"
Storyboard.TargetProperty="Opacity" To="1"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="ValidationStates">
<VisualState x:Name="Valid"/>
<VisualState x:Name="Invalid">
<Storyboard>
<DoubleAnimation Duration="0" Storyboard.TargetName="InvalidVisualElement" Storyboard.TargetProperty="Opacity" To="1"/>
<ColorAnimation Duration="0" Storyboard.TargetName="FocusVisual" Storyboard.TargetProperty="(Fill).Color" To="#FFFFFFFF"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Rectangle x:Name="FocusVisual"
Fill="Transparent"
Stroke="Transparent"
StrokeThickness="0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
IsHitTestVisible="false"
Opacity="0"
/>
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}"/>
<Rectangle x:Name="InvalidVisualElement" Stroke="#FFDC000C" StrokeThickness="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" IsHitTestVisible="False" Opacity="0"/>
<Rectangle x:Name="RightGridLine" VerticalAlignment="Stretch" Width="1" Grid.Column="1"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
and you add the CellStyle to the DataGrid
<data:DataGrid x:Name="uiDataGrid"
CellStyle="{StaticResource NonSelectableDataGridCellStyle}"
>
...
</data:DataGrid>
You can also add "invisible" column:
<sdk:DataGrid.Columns>
<sdk:DataGridTextColumn Binding="{Binding Path=Nothing}" MinWidth="0" MaxWidth="0" />
And make it current whenever current cell is changed:
Private Sub _CurrentCellChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.CurrentCellChanged
If Me.CurrentColumn IsNot Nothing Then Me.CurrentColumn = Me.Columns(0)
End Sub
This was suitable for me.