WPF VisualStateManager.GoToState - wpf

I try to change the state for all the buttons in my program
I got this style for button:
<Style TargetType="{x:Type Button}">
<Setter Property="Foreground" Value="White"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="StateMouseOver">
<Storyboard>
<ColorAnimation Storyboard.TargetName="UpperBorder" Duration="00:00:0.5" Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)" To="#FF5086C4"/>
</Storyboard>
</VisualState>
<VisualState x:Name="StatePressed">
<Storyboard>
<ColorAnimation Storyboard.TargetName="UpperBorder" Duration="00:00:0.05" Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)" To="#FF21214E"/>
</Storyboard>
</VisualState>
<VisualState x:Name="StateDisabled">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="UpperBorder" Duration="00:00:0.5" Storyboard.TargetProperty="(UIElement.Opacity)" To="0"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="Lower" Cursor="Hand" BorderThickness="1" CornerRadius="4" Background="Gray" ></Border>
<Border MouseEnter="UpperBorder_MouseEnter" x:Name="UpperBorder" Cursor="Hand" CornerRadius="4" Background="#FF0657E8">
<Border.Effect>
<DropShadowEffect BlurRadius="10"/>
</Border.Effect>
</Border>
<ContentPresenter Cursor="Hand" Margin="8,8,8,8" HorizontalAlignment="Center" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
in this event: MouseEnter="UpperBorder_MouseEnter I want the change will take effect on all the buttons in my program (but the function VisualStateManager.GoToState take as parameter only spesific button)
how can I do that?

The button already have MouseOver state in CommonStates group. See Button Styles and Templates. The state auto set in the Button class when mouse over.
Is that what you want ?

Related

VisualStateManager VisualGroup precedence

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.

Highlight selected bar in different color in wpf

I have a WPF application where I have a bar chart.
By default the color of bar is steel blue.
I want a functionality where when a users selects a bar, it should be highlighted in a different color i.e. red to indicate that is the product referring to. Please guide me how can I achieve this.
Currently I have used the following columndatapoint style.
<Style
x:Key="MyColumnDataPointStyle"
TargetType="charting:ColumnDataPoint">
<Setter Property="Background" Value="SteelBlue"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="charting:ColumnDataPoint">
<Border
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Opacity="1"
x:Name="Root">
<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="MouseOverHighlight"
Storyboard.TargetProperty="Opacity"
To="0.6"
Duration="0"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="SelectionStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.1"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Unselected"/>
<VisualState x:Name="Selected">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="SelectionHighlight"
Storyboard.TargetProperty="Opacity"
To="0.6"
Duration="0"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="RevealStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.5"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Shown">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="Root"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Hidden">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="Root"
Storyboard.TargetProperty="Opacity"
To="0"
Duration="0"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid
Background="{TemplateBinding Background}">
<Rectangle>
<Rectangle.Fill>
<LinearGradientBrush>
<GradientStop
Color="#77ffffff"
Offset="0"/>
<GradientStop
Color="#00ffffff"
Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Border
BorderBrush="#ccffffff"
BorderThickness="1">
<Border
BorderBrush="#77ffffff"
BorderThickness="1"/>
</Border>
<Rectangle x:Name="SelectionHighlight" Fill="Red" Opacity="0"/>
<Rectangle x:Name="MouseOverHighlight" Fill="White" Opacity="0"/>
</Grid>
<ToolTipService.ToolTip>
<StackPanel>
<ContentControl
Content="{TemplateBinding FormattedIndependentValue}"
FontWeight="Bold"/>
<ContentControl
Content="{TemplateBinding FormattedDependentValue}"/>
</StackPanel>
</ToolTipService.ToolTip>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
To do this in the MVVM pattern I would create a ViewModel class for your ColumnDataPoint.
This ViewModel contains a bool property e.g. called IsActive.
You can then bind the bar's DataContext to that ViewModel and in your style you can set a DataTrigger bound to that property.
To change that property you can create a command in your ViewModel which will be executed when clicking the bar
Here is a small example:
<Rectangle Fill="SteelBlue"
DataContext="{Binding YourViewModel}">
<Rectangle.Style>
<Style TargetType="Rectangle">
<Style.Triggers>
<DataTrigger Binding="{Binding IsActive}" Value="true">
<Setter Property="Stroke" Value="Chartreuse"/>
<Setter Property="StrokeThickness" Value="5"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonUp">
<command:EventToCommand Command="{Binding ClickingBarCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Rectangle>
To use the "i" and "command" namespace you have to add
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:command="http://www.galasoft.ch/mvvmlight"
Hopefully this was helpful to you
cheers

Silverlight custom button

I've create a style for a button:
<Style x:Key="TicketOnBizOptionsButton" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Disabled">
<Storyboard>
<ColorAnimation Duration="0" To="#FFC0C0C0" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" Storyboard.TargetName="border"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Duration="0" To="#FF14548C" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" Storyboard.TargetName="border"/>
<ColorAnimation Duration="0" To="White" Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="Content"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="border" BorderThickness="1" Background="#FFF2F2F2" CornerRadius="8" BorderBrush="#FFD5D5D5">
<Border.Effect>
<DropShadowEffect Direction="285" ShadowDepth="2" Color="#FFDFDFDF" BlurRadius="2"/>
</Border.Effect>
<Button Content="" Margin="-1" Width="105" BorderBrush="{x:Null}" Foreground="White" Background="{x:Null}" Opacity="0"/>
</Border>
<TextBlock x:Name="Content" Margin="5,5,5,5" Text="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The style works correctly and the button to.
But i've notice some erratic behavior when i click on the button.
Sometimes only works when clicking directly above the text other times only on the border...
The border that i've added has any effect on this??
Thanks in advance!
<Style x:Key="TicketOnBizOptionsButton" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Disabled">
<Storyboard>
<ColorAnimation Duration="0" To="#FFC0C0C0" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" Storyboard.TargetName="border"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Duration="0" RepeatBehavior="1x" To="#FF14548C" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" Storyboard.TargetName="border"/>
<ColorAnimation Duration="0" RepeatBehavior="1x" To="White" Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="Content"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="border" BorderThickness="1" Background="#FFF2F2F2" CornerRadius="8" BorderBrush="#FFD5D5D5">
<Border.Effect>
<DropShadowEffect Direction="285" ShadowDepth="2" Color="#FFDFDFDF" BlurRadius="2"/>
</Border.Effect>
</Border>
<TextBlock x:Name="Content" Margin="5,5,5,5" Text="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The problem was that you were using a button in your template, so once you fired the pressed state it was causing some problems probably with the other button inside the template. I just removed the one inside de border and it worked well.
Hope it helps.

TextBox malfunctioning on style

I'm using the following style on my wpf TextBox.
<Style x:Key="TextBoxStyle" TargetType="{x:Type TextBox}">
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Background" Value="White" />
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Padding" Value="2"/>
<Setter Property="BorderBrush" Value="Gray"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Grid x:Name="Root">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.3">
<VisualTransition.GeneratedEasingFunction>
<QuarticEase EasingMode="EaseOut"/>
</VisualTransition.GeneratedEasingFunction>
</VisualTransition>
</VisualStateGroup.Transitions>
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Duration="0" To="DarkGray" Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)" Storyboard.TargetName="Border" />
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled"/>
<VisualState x:Name="ReadOnly"/>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused">
<Storyboard>
<ColorAnimation Duration="0" To="Black" Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)" Storyboard.TargetName="Border" />
</Storyboard>
</VisualState>
<VisualState x:Name="Unfocused"/>
</VisualStateGroup>
<VisualStateGroup x:Name="ValidationStates">
<VisualState x:Name="Valid"/>
<VisualState x:Name="InvalidUnfocused"/>
<VisualState x:Name="InvalidFocused"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="Border" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="1" BorderBrush="Gray">
<ScrollViewer x:Name="ContentElement" BorderThickness="0" IsTabStop="False" VerticalContentAlignment="Center" Padding="5,0,0,0" VerticalAlignment="Center" Margin="0,0,22,0"/>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
On using this style the textbox stops working. If i click on the textbox the mouse pointer disappears, no focus or text appears. What is wrong with this style?
Rename your scrollbox, and it will work
<ScrollViewer x:Name="PART_ContentHost" BorderThickness="0" IsTabStop="False" VerticalContentAlignment="Center" Padding="5,0,0,0" VerticalAlignment="Center" Margin="0,0,22,0"/>
hope this helps
It seems your Xaml did not provide a place for interaction with the keyboard/mouse. I'm not alltogether sure what you are trying to design, but if you place a TextBox inside your ScrollViewer, your template will stop exhibiting the 'malfunction' you are describing...
<Border x:Name="Border" Background="{TemplateBinding Background}" BorderBrush="Gray" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="1">
<ScrollViewer x:Name="ContentElement" Margin="0,0,22,0" Padding="5,0,0,0" BorderThickness="0" IsTabStop="False" VerticalAlignment="Center" VerticalContentAlignment="Center">
<TextBox />
</ScrollViewer>
</Border>
This snippet shows a modification to your Xaml where the ScrollViewer contains a TextBox. The MouseDown event sets focus on the control, and keyboard interaction occurs as expected.

XAML - VisualGroupState for HyperlinkButton (whats wrong?)

Trying to figure out what I'm doing wrong (first time playing with Visual States). Can anyone point me to my problem? The app is crashing ungracefully, nothing else to help beyond that.
Heres the xaml
<Style TargetType="HyperlinkButton">
<Setter Property="Foreground" Value="{StaticResource HyperlinkTextBrush}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="HyperlinkButton">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<Storyboard>
<ColorAnimation BeginTime="0" Duration="0.5"
Storyboard.TargetName="content"
Storyboard.TargetProperty="(Control.Foreground).(SolidColorBrush.Color)"
To="Red" />
</Storyboard>
</VisualState>
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation BeginTime="0" Duration="0.5"
Storyboard.TargetName="content"
Storyboard.TargetProperty="(Control.Foreground).(SolidColorBrush.Color)"
To="White" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid>
<ContentPresenter x:Name="content" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Thanks!
There is 3 places which you should correct:
1) The VisualStateManager.VisualStateGroups tag must be situated inside the root control like a Grid and not in the ControlTemplate.
2) The ContentPresenter class doesn't have the Foreground property. But this property exists in the ContentControl class. After you replace this control, add explicit bindings for the properties Content and Foreground.
3) The value of the Duration property should be in seconds. Although you can use the expression Duration="1" which means 1 day, the value 0.5 crashes the application. Half of a second looks like 0:0:0.5.
Here is the fixed style:
<Style TargetType="HyperlinkButton">
<Setter Property="Foreground" Value="{StaticResource HyperlinkTextBrush}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="HyperlinkButton">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<Storyboard>
<ColorAnimation Duration="0:0:0.5"
Storyboard.TargetName="content"
Storyboard.TargetProperty="(Control.Foreground).(SolidColorBrush.Color)"
To="Red" />
</Storyboard>
</VisualState>
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Duration="0:0:0.5"
Storyboard.TargetName="content"
Storyboard.TargetProperty="(Control.Foreground).(SolidColorBrush.Color)"
To="White" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentControl x:Name="content" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}"
Foreground="{TemplateBinding Foreground}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Resources