I want to change the Foreground (font color) of the mouse-over-day:
I've oriented myself on the following stackoverflow-question How Change datepicker's Selected Date Text Color (White) and also on the general calendar-style (github) of the mahapps-metro framework.
I not very good at styles and it took me a whole day to get the following output:
It changed the font color of the mouse-over day, nice! But the style for Background and selected cell is gone :(
<DatePicker
x:Name="dtpEnddate">
<DatePicker.Resources>
<Color
x:Key="NewColor">Pink</Color>
</DatePicker.Resources>
<DatePicker.CalendarStyle>
<Style
BasedOn="{StaticResource MahApps.Metro.Styles.BaseMetroCalendar}"
TargetType="Calendar">
<Setter
Property="CalendarDayButtonStyle">
<Setter.Value>
<Style
BasedOn="{StaticResource MahApps.Metro.Styles.MetroCalendarDayButtonStyle}"
TargetType="{x:Type CalendarDayButton}">
<Setter
Property="Template">
<Setter.Value>
<ControlTemplate
TargetType="{x:Type CalendarDayButton}">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup
x:Name="CommonStates">
<VisualStateGroup.Transitions>
<VisualTransition
GeneratedDuration="0:0:0.1" />
</VisualStateGroup.Transitions>
<VisualState
x:Name="Normal" />
<VisualState
x:Name="MouseOver">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="HighlightBackground"
Storyboard.TargetProperty="Opacity"
To="0.75"
Duration="0" />
<ColorAnimation
Duration="0"
To="{StaticResource NewColor}"
Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)"
Storyboard.TargetName="NormalText" />
</Storyboard>
</VisualState>
<VisualState
x:Name="Pressed">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="HighlightBackground"
Storyboard.TargetProperty="Opacity"
To="0.9"
Duration="0" />
</Storyboard>
</VisualState>
<VisualState
x:Name="Disabled">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="HighlightBackground"
Storyboard.TargetProperty="Opacity"
To="0"
Duration="0" />
<DoubleAnimation
Storyboard.TargetName="NormalText"
Storyboard.TargetProperty="Opacity"
To=".35"
Duration="0" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter
x:Name="NormalText"
TextElement.Foreground="#000000"
Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
<Rectangle
x:Name="HighlightBackground"
Fill="{DynamicResource MahApps.Brushes.Accent4}"
Opacity="0" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Setter.Value>
</Setter>
</Style>
</DatePicker.CalendarStyle>
I tried to copy the complete code inside of the original source from <Style x:Key="MahApps.Styles.CalendarDayButton" TargetType="{x:Type CalendarDayButton}"> with the additional ColorAnimation inside of the MouseOver-VisualState, but it ended up in the same result without background and selected cell.
Do you have any tips how to change the font color of the day on mouse-over? I would prefer to create a new style-snippet based on the frameworks style, not to recreate the whole style.
Here is some additional code from my App.xaml. I don't know if this is the reason:
<Color
x:Key="AccentColor">#9e0000</Color>
<Color
x:Key="AccentColor2">#9e0000
</Color>
<Color
x:Key="AccentColor3">#9e0000
</Color>
<Color
x:Key="AccentColor4">#9e0000
</Color>
<Color
x:Key="AccentColorWhite">#FFFFFF</Color>
<SolidColorBrush
x:Key="lightGray"
Color="LightGray"></SolidColorBrush>
<SolidColorBrush
x:Key="HighlightBrush"
Color="{StaticResource HighlightColor}" />
<SolidColorBrush
x:Key="AccentBaseColorBrush"
Color="{StaticResource AccentBaseColor}" />
<SolidColorBrush
x:Key="AccentColorBrush"
Color="{StaticResource AccentColor}" />
<SolidColorBrush
x:Key="AccentColorBrush2"
Color="{StaticResource AccentColor2}" />
<SolidColorBrush
x:Key="AccentColorBrush3"
Color="{StaticResource AccentColor3}" />
<SolidColorBrush
x:Key="AccentColorBrush4"
Color="{StaticResource AccentColor4}" />
<SolidColorBrush
x:Key="WindowTitleColorBrush"
Color="{StaticResource AccentColor}" />
<Color
x:Key="IdealForegroundColor">White</Color>
<SolidColorBrush
x:Key="IdealForegroundColorBrush"
Color="{StaticResource IdealForegroundColor}" />
<SolidColorBrush
x:Key="IdealForegroundDisabledBrush"
Opacity="0.4"
Color="{StaticResource IdealForegroundColor}" />
<SolidColorBrush
x:Key="AccentSelectedColorBrush"
Color="{StaticResource IdealForegroundColor}" />
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary
Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<!-- Flat slider -->
<ResourceDictionary
Source="pack://application:,,,/MahApps.Metro;component/Styles/FlatSlider.xaml" />
<ResourceDictionary
Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<ResourceDictionary
Source="pack://application:,,,/MahApps.Metro;component/Styles/Colors.xaml" />
<!-- Accent and AppTheme setting -->
<ResourceDictionary
Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.AnimatedTabControl.xaml" />
<ResourceDictionary
Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/Red.xaml" />
<ResourceDictionary
Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseLight.xaml" />
</ResourceDictionary.MergedDictionaries>
Original Solution for Version 2.4.9
Unfortunately, if you need to adapt any part of control templates like visual states, you have to rewrite or copy it completely and adapt the parts in question. Styles can be based on others, but control templates cannot. However, as you already found out, you only have to adapt the calendar button style, not all styles for calendar.
Your style seems to be heavily edited and compared to the base style, there is a lot missing, which causes the missing visual representation. If you want to change the mouse over foreground color, you only have to add a Trigger to the control template triggers, that observes if IsMouseOver is True. Then you can set the Foreground brush to your NewBrush (I renamed it to brush).
<!-- IsMouseOver -->
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="NormalText" Property="TextElement.Foreground" Value="{StaticResource NewBrush}" />
</Trigger>
In this case, change your resource to a brush instead of a color (Foreground is of type Brush).
<SolidColorBrush x:Key="NewBrush" Color="Pink"/>
This is the whole DatePicker with the copied and adapted style for the calendar day buttons.
<DatePicker x:Name="dtpEnddate">
<DatePicker.Resources>
<SolidColorBrush x:Key="NewColor" Color="Pink"/>
</DatePicker.Resources>
<DatePicker.CalendarStyle>
<Style TargetType="{x:Type Calendar}"
BasedOn="{StaticResource MahApps.Styles.Calendar.DateTimePicker}">
<Setter Property="CalendarDayButtonStyle">
<Setter.Value>
<Style TargetType="{x:Type CalendarDayButton}">
<Setter Property="FontFamily" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Calendar}}, Path=FontFamily, Mode=OneWay}" />
<Setter Property="FontSize" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Calendar}}, Path=FontSize, Mode=OneWay}" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="MinHeight" Value="5" />
<Setter Property="MinWidth" Value="5" />
<Setter Property="Padding" Value="5 1" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type CalendarDayButton}">
<Grid>
<Rectangle x:Name="TodayBackground"
Fill="{DynamicResource MahApps.Brushes.Accent}"
Opacity="0" />
<Rectangle x:Name="SelectedBackground"
Fill="{DynamicResource MahApps.Brushes.Accent4}"
Opacity="0" />
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}" />
<Rectangle x:Name="HighlightBackground"
Fill="{DynamicResource MahApps.Brushes.Accent4}"
Opacity="0" />
<Path x:Name="Blackout"
Margin="3"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Data="M8.1772461,11.029181 L10.433105,11.029181 L11.700684,12.801641 L12.973633,11.029181 L15.191895,11.029181 L12.844727,13.999395 L15.21875,17.060919 L12.962891,17.060919 L11.673828,15.256231 L10.352539,17.060919 L8.1396484,17.060919 L10.519043,14.042364 z"
Fill="{DynamicResource MahApps.Brushes.Accent3}"
Opacity="0"
RenderTransformOrigin="0.5,0.5"
Stretch="Fill" />
<ContentPresenter x:Name="NormalText"
Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
TextElement.Foreground="{TemplateBinding Foreground}" />
<Rectangle x:Name="DayButtonFocusVisual"
IsHitTestVisible="false"
Stroke="{DynamicResource MahApps.Brushes.Accent3}"
Visibility="Collapsed" />
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.1" />
</VisualStateGroup.Transitions>
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="HighlightBackground"
Storyboard.TargetProperty="Opacity"
To="0.75"
Duration="0" />
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="HighlightBackground"
Storyboard.TargetProperty="Opacity"
To="0.9"
Duration="0" />
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="HighlightBackground"
Storyboard.TargetProperty="Opacity"
To="0"
Duration="0" />
<DoubleAnimation Storyboard.TargetName="NormalText"
Storyboard.TargetProperty="Opacity"
To=".35"
Duration="0" />
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="ActiveStates">
<VisualState x:Name="Active" />
<VisualState x:Name="Inactive" />
</VisualStateGroup>
<VisualStateGroup x:Name="BlackoutDayStates">
<VisualState x:Name="NormalDay" />
<VisualState x:Name="BlackoutDay" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
<ControlTemplate.Triggers>
<!-- IsInactive -->
<Trigger Property="IsInactive" Value="True">
<Setter TargetName="NormalText" Property="TextElement.Foreground" Value="{DynamicResource MahApps.Brushes.Gray2}" />
</Trigger>
<!-- IsMouseOver -->
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="NormalText" Property="TextElement.Foreground" Value="{StaticResource NewColor}" />
</Trigger>
<!-- IsSelected -->
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="DayButtonFocusVisual" Property="Visibility" Value="Visible" />
<Setter TargetName="NormalText" Property="TextElement.Foreground" Value="{DynamicResource MahApps.Brushes.AccentBase}" />
</Trigger>
<!-- IsToday, IsTodayHighlighted and IsSelected -->
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Calendar}}, Path=IsTodayHighlighted}" Value="True" />
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsToday}" Value="True" />
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsSelected}" Value="True" />
</MultiDataTrigger.Conditions>
<Setter TargetName="DayButtonFocusVisual" Property="Stroke" Value="{DynamicResource MahApps.Brushes.Gray1}" />
<Setter TargetName="DayButtonFocusVisual" Property="Visibility" Value="Visible" />
<Setter TargetName="NormalText" Property="TextElement.Foreground" Value="{DynamicResource MahApps.Brushes.Accent}" />
</MultiDataTrigger>
<!-- IsToday and IsTodayHighlighted -->
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Calendar}}, Path=IsTodayHighlighted}" Value="True" />
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsToday}" Value="True" />
</MultiDataTrigger.Conditions>
<Setter TargetName="NormalText" Property="TextElement.Foreground" Value="{DynamicResource MahApps.Brushes.Selected.Foreground}" />
<Setter TargetName="TodayBackground" Property="Opacity" Value="1" />
</MultiDataTrigger>
<!-- IsBlackedOut -->
<Trigger Property="IsBlackedOut" Value="True">
<Setter TargetName="Blackout" Property="Opacity" Value="1" />
</Trigger>
<!-- IsToday and IsBlackedOut -->
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsToday" Value="True" />
<Condition Property="IsBlackedOut" Value="True" />
</MultiTrigger.Conditions>
<Setter TargetName="Blackout" Property="Fill" Value="{DynamicResource MahApps.Brushes.Accent}" />
<Setter TargetName="TodayBackground" Property="Opacity" Value="0.5" />
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="VerticalContentAlignment" Value="Center" />
</Style>
</Setter.Value>
</Setter>
</Style>
</DatePicker.CalendarStyle>
</DatePicker>
This is what the result looks like for Red theme (might not be yours).
Update for Version 1.6.5
As you mentioned later in the comments, you are using MahApps.Metro version 1.6.5. Styles and templates change over time. The old version is incompatible with the current version.
Here is an adapted style based on the default style of the correct version.
<DatePicker x:Name="dtpEnddate">
<DatePicker.Resources>
<SolidColorBrush x:Key="NewBrush" Color="Pink"/>
</DatePicker.Resources>
<DatePicker.CalendarStyle>
<Style TargetType="{x:Type Calendar}"
BasedOn="{StaticResource MahApps.Metro.Styles.MetroCalendar}">
<Setter Property="CalendarDayButtonStyle">
<Setter.Value>
<Style TargetType="{x:Type CalendarDayButton}">
<Setter Property="FontFamily" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Calendar}}, Path=FontFamily, Mode=OneWay}" />
<Setter Property="FontSize" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Calendar}}, Path=FontSize, Mode=OneWay}" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="MinHeight" Value="5" />
<Setter Property="MinWidth" Value="5" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type CalendarDayButton}">
<Grid>
<Rectangle x:Name="TodayBackground"
Fill="{DynamicResource AccentColorBrush}"
Opacity="0" />
<Rectangle x:Name="SelectedBackground"
Fill="{DynamicResource AccentColorBrush4}"
Opacity="0" />
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}" />
<Rectangle x:Name="HighlightBackground"
Fill="{DynamicResource AccentColorBrush4}"
Opacity="0" />
<Path x:Name="Blackout"
Margin="3"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Data="M8.1772461,11.029181 L10.433105,11.029181 L11.700684,12.801641 L12.973633,11.029181 L15.191895,11.029181 L12.844727,13.999395 L15.21875,17.060919 L12.962891,17.060919 L11.673828,15.256231 L10.352539,17.060919 L8.1396484,17.060919 L10.519043,14.042364 z"
Fill="{DynamicResource AccentColorBrush3}"
Opacity="0"
RenderTransformOrigin="0.5,0.5"
Stretch="Fill" />
<ContentPresenter x:Name="NormalText"
Margin="5 1 5 1"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
TextElement.Foreground="{TemplateBinding Foreground}" />
<Rectangle x:Name="DayButtonFocusVisual"
IsHitTestVisible="false"
Stroke="{DynamicResource AccentColorBrush3}"
Visibility="Collapsed" />
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.1" />
</VisualStateGroup.Transitions>
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="HighlightBackground"
Storyboard.TargetProperty="Opacity"
To="0.75"
Duration="0" />
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="HighlightBackground"
Storyboard.TargetProperty="Opacity"
To="0.9"
Duration="0" />
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="HighlightBackground"
Storyboard.TargetProperty="Opacity"
To="0"
Duration="0" />
<DoubleAnimation Storyboard.TargetName="NormalText"
Storyboard.TargetProperty="Opacity"
To=".35"
Duration="0" />
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="ActiveStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0" />
</VisualStateGroup.Transitions>
<VisualState x:Name="Active" />
<VisualState x:Name="Inactive">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="NormalText"
Storyboard.TargetProperty="(TextElement.Foreground)"
Duration="0">
<DiscreteObjectKeyFrame Value="{DynamicResource GrayBrush2}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="BlackoutDayStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0" />
</VisualStateGroup.Transitions>
<VisualState x:Name="NormalDay" />
<VisualState x:Name="BlackoutDay">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="Blackout"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="NormalText" Property="TextElement.Foreground" Value="{DynamicResource NewBrush}" />
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="DayButtonFocusVisual" Property="Visibility" Value="Visible" />
<Setter TargetName="NormalText" Property="TextElement.Foreground" Value="{DynamicResource AccentColorBrush}" />
</Trigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Calendar}}, Path=IsTodayHighlighted}" Value="True" />
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsToday}" Value="True" />
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsSelected}" Value="True" />
</MultiDataTrigger.Conditions>
<Setter TargetName="DayButtonFocusVisual" Property="Stroke" Value="{DynamicResource GrayBrush1}" />
<Setter TargetName="DayButtonFocusVisual" Property="Visibility" Value="Visible" />
<Setter TargetName="NormalText" Property="TextElement.Foreground" Value="{DynamicResource AccentColorBrush}" />
</MultiDataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Calendar}}, Path=IsTodayHighlighted}" Value="True" />
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsToday}" Value="True" />
</MultiDataTrigger.Conditions>
<Setter TargetName="NormalText" Property="TextElement.Foreground" Value="{DynamicResource AccentSelectedColorBrush}" />
<Setter TargetName="TodayBackground" Property="Opacity" Value="1" />
</MultiDataTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsToday" Value="True" />
<Condition Property="IsBlackedOut" Value="True" />
</MultiTrigger.Conditions>
<Setter TargetName="Blackout" Property="Fill" Value="{DynamicResource AccentColorBrush}" />
<Setter TargetName="TodayBackground" Property="Opacity" Value="0.5" />
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="VerticalContentAlignment" Value="Center" />
</Style>
</Setter.Value>
</Setter>
</Style>
</DatePicker.CalendarStyle>
</DatePicker>
I'm trying to make VisualBrush that automatically fades in/out when set, but unfortunately it doesn't work as it should. Instead of actually fading it disappears or appears right away totally ignoring storyboard - or I'm trying to catch wrong event.
<VisualBrush x:Key="CustomHatchBrush" TileMode="None" Viewport="0,0,100,100" ViewportUnits="Absolute" Viewbox="0,0,100,100" ViewboxUnits="Absolute">
<VisualBrush.Visual>
<Canvas>
<Canvas.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:0.2" From="0" To="1" Storyboard.TargetProperty="(Canvas.Opacity)" RepeatBehavior="1x" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="FrameworkElement.Unloaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:0.2" From="1" To="0" Storyboard.TargetProperty="(Canvas.Opacity)" RepeatBehavior="1x" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Canvas.Triggers>
<Rectangle Canvas.Top="0" Canvas.Left="0" Width="100" Height="100" Fill="Orange" />
<Rectangle Canvas.Top="0" Canvas.Left="0" Width="100" Height="100" Fill="{DynamicResource CaretBrush}" />
</Canvas>
</VisualBrush.Visual>
</VisualBrush>
I generally want to use it inside Template of ListBoxItem as BorderBrush, something like that:
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border x:Name="ca" BorderThickness="3" SnapsToDevicePixels="true" Padding="0">
<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="4" Background="Transparent" HorizontalAlignment="Center" VerticalAlignment="Center" SnapsToDevicePixels="true" Padding="0">
<ContentPresenter HorizontalAlignment="Stretch" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
</Border>
<ControlTemplate.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Prop1}" Value="true"/>
<Condition Binding="{Binding Prop2}" Value="true"/>
</MultiDataTrigger.Conditions>
<Setter Property="BorderBrush" TargetName="ca" Value="{DynamicResource CustomHatchBrush}"/>
</MultiDataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Prop1}" Value="true"/>
<Condition Binding="{Binding Prop2}" Value="false"/>
</MultiDataTrigger.Conditions>
<Setter Property="BorderBrush" TargetName="ca" Value="{DynamicResource CustomHatchBrush2}"/>
</MultiDataTrigger>
<DataTrigger Binding="{Binding Prop1}" Value="false">
<Setter Property="BorderBrush" TargetName="ca" Value="Transparent"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
I tried many ways of applying storyboard, for example inside bindings, but it always finishes instantly completely ignoring Storyboard duration.
What am I missing? This control works fine in general (objects have name and have multiple instances, so something could go wrong), I just can't create visual effect that I would want to achieve.
I have been for 2 days now trying to develop my own WPF textbox for no avail.
My initial try was inheriting from a control and then adding a template with all the stuff I wanted (a border and an asterisk in the outside).
Generic.xaml file:
<Style TargetType="{x:Type local:BdlTextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:BdlTextBox">
<Grid x:Name="ContentGrid">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="8"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" x:Name="Tbl" Text="*" Foreground="Red" FontSize="15" Margin="0,-4,0,0"
Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:BdlTextBox}},
Path=IsRequired, Converter={StaticResource myBoolToVisibilityConverter}}"/>
<Rectangle Grid.Column="1" x:Name="Bg" Fill="Red" Opacity="0"/>
<TextBox Grid.Column="1" x:Name="Tb" Margin="1,1,1,1"/>
</Grid>
</Grid>
<ControlTemplate.Resources>
<Storyboard x:Key="flashAnimation">
<DoubleAnimation Storyboard.TargetName="Bg" Storyboard.TargetProperty="Opacity" From="0" To="1" AutoReverse="True" Duration="0:0:0.5" RepeatBehavior="2x" />
<DoubleAnimation Storyboard.TargetName="Bg" Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:0.5" BeginTime="0:0:2"/>
</Storyboard>
</ControlTemplate.Resources>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=HasValidationError}" Value="True" >
<DataTrigger.EnterActions>
<BeginStoryboard Name="flash" Storyboard="{StaticResource flashAnimation}" />
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="flash"/>
</DataTrigger.ExitActions>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=HasValidationError}" Value="False" >
<Setter TargetName="Bg" Property="Opacity" Value="0"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The problem is: I cannot use the control as a Textbox (the reason is obvious). I can't even properly use the Text property. So I was wondering what could be done to solve this problem.
Dependency Properties are also a problem. I have tried to "clone" the Text property from the Textbox "Tb", but failed too.
I'm new to WPF and have been looking at a lot of articles and videos but I've been unable to find a solution. What I have is a button which displays an image and text within a stackpanel. I would like to make ONLY the textblock move one pixel to the right and down when the button is pressed but I cant seem to figure out a way to target only the TextBlock. Any help would be greatly appreciated. THANKS
<Style x:Key="appFlatButtonLarge" TargetType="{x:Type localUI:ImageButton}">
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="MinHeight" Value="23"/>
<Setter Property="MinWidth" Value="75"/>
<Setter Property="Foreground" Value="{StaticResource appPrimaryBackColorDark}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type localUI:ImageButton}">
<Border Name="Border" BorderBrush="LightGray" BorderThickness="1" Background="White" >
<StackPanel Name="Panel" Height="Auto" Orientation="Horizontal" Background="Transparent">
<Image Name="ibImage" Source="{TemplateBinding ImageSource}" Margin="5" Width="Auto" Height="Auto" Stretch="None" RenderOptions.BitmapScalingMode="NearestNeighbor" RenderOptions.EdgeMode="Aliased"/>
<TextBlock Name="ibTextBlock" Text="{TemplateBinding Content}" HorizontalAlignment="Left" FontWeight="Bold" Margin="5,0,0,0" VerticalAlignment="Center" FontSize="12" />
</StackPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsKeyboardFocused" Value="true">
<Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource appPrimaryBackColorDark}" />
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="Panel" Property="Background" Value="{StaticResource appButtonBackColorPressed}" />
<Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource appPrimaryBackColorDark}" />
<Setter TargetName="ibImage" Property="Source" Value="{Binding Path=ImageSourceHot, RelativeSource={RelativeSource AncestorType={x:Type localUI:ImageButton}} }" />
</Trigger>
<Trigger Property="IsPressed" Value="true">
<Setter TargetName="Border" Property="BorderBrush" Value="Green" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Just use a TranslateTransform animation. make sure to use RenderTransform and not LayoutTransform as LayoutTransform will actually change the Layout which might not be desirable when the parent of your TextBlock and Image is a StackPanel
So in your Style if I switch the ControlTemplate definition to:
<ControlTemplate TargetType="{x:Type localUI:ImageButton}">
<Border x:Name="Border"
Background="White"
BorderBrush="LightGray"
BorderThickness="1">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver" />
<VisualState x:Name="Pressed">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="ibTextBlock"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
<EasingDoubleKeyFrame KeyTime="0"
Value="5" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="ibTextBlock"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)">
<EasingDoubleKeyFrame KeyTime="0"
Value="5" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<StackPanel x:Name="Panel"
Height="Auto"
Background="Transparent"
Orientation="Horizontal">
<Image Name="ibImage"
Width="Auto"
Height="Auto"
Margin="5"
RenderOptions.BitmapScalingMode="NearestNeighbor"
RenderOptions.EdgeMode="Aliased"
Source="{TemplateBinding ImageSource}"
Stretch="None" />
<TextBlock x:Name="ibTextBlock"
Margin="5,0,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
FontSize="12"
FontWeight="Bold"
RenderTransformOrigin="0.5,0.5"
Text="{TemplateBinding Content}">
<TextBlock.RenderTransform>
<TransformGroup>
<ScaleTransform />
<SkewTransform />
<RotateTransform />
<TranslateTransform />
</TransformGroup>
</TextBlock.RenderTransform>
</TextBlock>
</StackPanel>
</Border>
<ControlTemplate.Triggers>
...
you should get what you're after.
Note
In both the Animation steps I've set
<EasingDoubleKeyFrame KeyTime="0" Value="5" />
you can change the Value to "1" or whatever you desire.
You could change the Margin-Property of your TextBlock with the same trigger that changes the BorderBrush.
Say you set Margin = "2,2,2,2" initially, and then you set it to "3,2,1,2" when the button is pressed.
Your TextBlock will 'move' by 1/96 inch (usually, you don't pixel in WPF).
You can also use negative margins, if needed.
I am looking to create an application in Visual Studio C# that mimics the Android pattern lock screen, and was wondering if anyone had any tips for doing so.
This is not a commercial project and no money will be made, just a bit of fun.
I have been playing around in WPF Projects, and am at a loss for ideas right now. The only way I have thought of would be to track the mouse on a MouseDown event, and use the paint features in C# to "paint" where the mouse has been, but I don't feel that this is the best solution.
Any ideas for doing this?
See if this chould help you is rough code.
public partial class PatternLock : UserControl
{
bool isMouseDown = false;
private ObservableCollection<ToggleButton> selectedobject = new ObservableCollection<ToggleButton>();
public PatternLock()
{
InitializeComponent();
}
internal ObservableCollection<int> buttons = new ObservableCollection<int>();
private void layoutroot_Checked(object sender, RoutedEventArgs e)
{
if (e.OriginalSource is ToggleButton)
buttons.Add(Convert.ToInt32(((ToggleButton)e.OriginalSource).Content));
}
private void layoutroot_Unchecked(object sender, RoutedEventArgs e)
{
if (e.OriginalSource is ToggleButton)
{
int i = Convert.ToInt32(((ToggleButton)e.OriginalSource).Content);
buttons.Remove(i);
}
}
internal void ResetPattern()
{
if (buttons != null)
{
buttons.Clear();
foreach (ToggleButton item in layoutroot.Children)
{
item.IsChecked = false;
}
}
}
}
XAML
<UserControl x:Class="WPFTestings.LockPattern.PatternLock"
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"
d:DesignHeight="300"
d:DesignWidth="300"
mc:Ignorable="d">
<UserControl.Resources>
<Style TargetType="{x:Type ToggleButton}">
<Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}" />
<Setter Property="BorderBrush" Value="{StaticResource ButtonNormalBorder}" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Foreground" Value="{DynamicResource TextBrush}" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Padding" Value="1" />
<Setter Property="FontSize" Value="50" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<ControlTemplate.Resources>
<Storyboard x:Key="HoverOn">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="HoverBorder"
Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.1000000" Value="0.5" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="HoverShineBorder"
Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.1000000" Value="1" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="HoverOff">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="HoverBorder"
Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="0" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="HoverShineBorder"
Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="0" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="CheckedOn">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="CheckedBorder"
Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.1000000" Value="0.5" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="CheckedOff">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="CheckedBorder"
Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="0" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="PressedOn">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="Pressed"
Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.1000000" Value="1" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="PressedOff">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="Pressed"
Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="0" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</ControlTemplate.Resources>
<Grid x:Name="grid">
<Border x:Name="Border"
Background="{DynamicResource NormalBrush}"
BorderBrush="{DynamicResource NormalBorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="50"
Padding="{TemplateBinding Padding}">
<Border.BitmapEffect>
<OuterGlowBitmapEffect GlowColor="Red" GlowSize="10" />
</Border.BitmapEffect>
</Border>
<Border x:Name="CheckedBorder"
Background="YellowGreen"
BorderBrush="Green"
BorderThickness="2"
CornerRadius="50"
Opacity="0"
Padding="{TemplateBinding Padding}">
<Border.BitmapEffect>
<OuterGlowBitmapEffect GlowColor="YellowGreen" GlowSize="10" />
</Border.BitmapEffect>
</Border>
<Border x:Name="HoverBorder"
Background="YellowGreen"
BorderBrush="{DynamicResource NormalBorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="50"
Opacity="0"
Padding="{TemplateBinding Padding}" />
<Border x:Name="HoverShineBorder"
Background="{DynamicResource HoverShineBrush}"
BorderBrush="{DynamicResource NormalBorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="50"
Opacity="0"
Padding="{TemplateBinding Padding}" />
<Border x:Name="Pressed"
Background="YellowGreen"
BorderBrush="Green"
BorderThickness="2"
CornerRadius="50"
Opacity="0"
Padding="{TemplateBinding Padding}" />
<Rectangle x:Name="Shine"
Height="Auto"
Margin="2,2,2,2"
VerticalAlignment="Stretch"
Opacity="1"
RadiusX="3"
RadiusY="3"
Stroke="{x:Null}">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0.5,0.042" EndPoint="0.5,0.971">
<GradientStop Offset="0" Color="#26FFFFFF" />
<GradientStop Offset="1" Color="#00FFFFFF" />
<GradientStop Offset="0.467" Color="#26FFFFFF" />
<GradientStop Offset="0.475" Color="#00FFFFFF" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<ContentPresenter Margin="4,4,4,4"
HorizontalAlignment="Center"
VerticalAlignment="Center"
RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Trigger.ExitActions>
<BeginStoryboard x:Name="HoverOff_BeginStoryboard" Storyboard="{StaticResource HoverOff}" />
</Trigger.ExitActions>
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource HoverOn}" />
</Trigger.EnterActions>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Trigger.ExitActions>
<BeginStoryboard x:Name="PressedOff_BeginStoryboard" Storyboard="{StaticResource PressedOff}" />
</Trigger.ExitActions>
<Trigger.EnterActions>
<BeginStoryboard x:Name="PressedOn_BeginStoryboard" Storyboard="{StaticResource PressedOn}" />
</Trigger.EnterActions>
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="true" />
<Trigger Property="IsChecked" Value="true">
<Trigger.ExitActions>
<BeginStoryboard x:Name="CheckedOff_BeginStoryboard" Storyboard="{StaticResource CheckedOff}" />
</Trigger.ExitActions>
<Trigger.EnterActions>
<BeginStoryboard x:Name="CheckedOn_BeginStoryboard" Storyboard="{StaticResource CheckedOn}" />
</Trigger.EnterActions>
<Setter TargetName="Pressed" Property="BitmapEffect">
<Setter.Value>
<OuterGlowBitmapEffect GlowColor="YellowGreen" GlowSize="10" />
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="#ADADAD" />
<Setter TargetName="Border" Property="Background" Value="{DynamicResource DisabledBackgroundBrush}" />
<Setter TargetName="Border" Property="BorderBrush" Value="{DynamicResource DisabledBorderBrush}" />
<Setter TargetName="grid" Property="Opacity" Value="0.5" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Foreground">
<Setter.Value>
<SolidColorBrush Color="{DynamicResource BlackColor}" />
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
<UniformGrid x:Name="layoutroot"
Columns="3"
Rows="3"
ToggleButton.Checked="layoutroot_Checked"
ToggleButton.Unchecked="layoutroot_Unchecked">
<ToggleButton x:Name="btn1"
Margin="5"
Content="1" />
<ToggleButton x:Name="btn2"
Margin="5"
Content="2" />
<ToggleButton x:Name="btn3"
Margin="5"
Content="3" />
<ToggleButton x:Name="btn4"
Margin="5"
Content="4" />
<ToggleButton x:Name="btn5"
Margin="5"
Content="5" />
<ToggleButton x:Name="btn6"
Margin="5"
Content="6" />
<ToggleButton x:Name="btn7"
Margin="5"
Content="7" />
<ToggleButton x:Name="btn8"
Margin="5"
Content="8" />
<ToggleButton x:Name="btn9"
Margin="5"
Content="9" />
</UniformGrid>
</UserControl>
useing this is add dialog and button to match this as
if (string.Concat(patternLock1.buttons).ToString() == "1359")
{
this.Close();
}
else
{
patternLock1.ResetPattern();
}