Silverlight; Change Grid's background on mouseover - c#

Simply i want to change the Grid's background color (in Silverlight) when the mouse enters and reset it when the mouse leaves.
So I tried different ways but no success. Here is what I have tried:
1: using EventTriggers:
<Grid.Triggers>
<EventTrigger RoutedEvent="MouseEnter">
<BeginStoryboard Storyboard="{StaticResouce mouseEnter}"/>
</EventTrigger>
</Grid.Triggers>
this doesn't work and say:
The member "IsMouseOver" is not recognized or is not accessible
2. using Style.Triggers
I tried setting some simple triggers in an Style with TargetType="Grid" but in Silverlight it seems there is no way to make Style.Triggers in XAML. Here is the code:
<Grid.Style>
<Style TargetType="Grid">
<Style.Triggers>
</Style.Triggers>
</Style>
</Grid.Style>
But it says:
The attachable property 'Triggers' was not found in type 'Style'.
3. using interaction libraries
I also used Interactivity.dll and interaction.dll but they didnt' work too.
Can anyone help how to change the grid background when the mouse enters in Silverlight?

There are three possible solutions:
First solution: Using VisualSates: Changing a Background on MouseOver in Silverlight can be done via VisualStates.
Here is an example:
<UserControl class="MyUserControlWithVisualStates">
<Grid x:Name="RootGrid" Background="UglyRed">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="Disabled"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation To="Green"
Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)"
Storyboard.TargetName="RootGrid"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused"/>
<VisualState x:Name="Unfocused"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<OtherGridContent ... />
</Grid>
</UserControl>
and code behind:
public partial class MyUserControlWithVisualStates : UserControl
{
private bool m_isMouseOver;
public MyUserControlWithVisualStates()
{
InitializeComponent();
RootGrid.MouseEnter += OnRootGridMouseEnter;
RootGrid.MouseLeave += OnRootGridMouseLeave;
}
private void UpdateVisualStates()
{
if ( m_isMouseOver )
VisualStateManager.GoToState( this, "MouseOver", true );
else
VisualStateManager.GoToState( this, "Normal", true );
}
private void OnRootGridMouseLeave( object sender, MouseEventArgs e )
{
m_isMouseOver = false;
UpdateVisualStates();
}
private void OnRootGridMouseEnter( object sender, MouseEventArgs e )
{
m_isMouseOver = true;
UpdateVisualStates();
}
}
Second solution: Changing properties via codebehind: The MouseEnter and MouseLeave event handlers can just change the grid's background color.
public partial class MyUserControl : UserControl
{
private bool m_isMouseOver;
public MyUserControl()
{
InitializeComponent();
RootGrid.MouseEnter += OnRootGridMouseEnter;
RootGrid.MouseLeave += OnRootGridMouseLeave;
}
private void UpdateBackground()
{
if (m_isMouseOver)
((SolidColorBrush) RootGrid.Background).Color = Colors.Red;
else
((SolidColorBrush) RootGrid.Background).Color = Colors.Green;
}
private void OnRootGridMouseLeave( object sender, MouseEventArgs e )
{
m_isMouseOver = false;
UpdateBackground();
}
private void OnRootGridMouseEnter( object sender, MouseEventArgs e )
{
m_isMouseOver = true;
UpdateBackground();
}
}
Third solution: Using triggers and actions in xaml:
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
<Grid x:Name="TheGrid" Background="Blue">
<Grid.Resources>
<SolidColorBrush x:Key="MouseOverBrush" Color="Green"/>
<SolidColorBrush x:Key="NormalBrush" Color="Red"/>
</Grid.Resources>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter" SourceName="TheGrid">
<ei:ChangePropertyAction
TargetName="TheGrid"
PropertyName="Background"
Value="{StaticResource MouseOverBrush}"/>
</i:EventTrigger>
<i:EventTrigger EventName="MouseLeave" SourceName="TheGrid">
<ei:ChangePropertyAction
TargetName="TheGrid"
PropertyName="Background"
Value="{StaticResource NormalBrush}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Grid>

Related

UWP Bindings in VisualState Setters

Is it actually possible to use bindings with the Setters Value property in VisualState, because when I try to use x:Bind the initial view of the page is not using the bindings and with Binding the page does not use them ever or do I need to do something additional?
For example if I use the layout below and I start the app with a width between 400 - 800 the PassInput Passwordbox will not have a placeholder. When I resize the window to more than 800 and then back it will finally have the placeholder.
Example:
<Page
x:Class="UWP.Learning.MainPage"
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"
mc:Ignorable="d"
x:Name="Page">
<RelativePanel Background="White">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="WindowSizeStates">
<VisualState x:Name="SmallState">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="400" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="PassInput.PlaceholderText" Value="{x:Bind MyPlaceHolder, Mode=OneWay}" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="WideState">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="800" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="PassInput.PlaceholderText" Value="{x:Null}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<TextBlock
Name="PassLabel"
RelativePanel.AlignTopWithPanel="True"
RelativePanel.AlignLeftWithPanel="True"
RelativePanel.AlignRightWithPanel="True"
Text="Pass input label"
HorizontalAlignment="Center" />
<PasswordBox
Name="PassInput"
RelativePanel.AlignLeftWithPanel="True"
RelativePanel.AlignRightWithPanel="True"
RelativePanel.Below="PassLabel"
VerticalAlignment="Center"
Margin="20,0" />
</RelativePanel>
</Page>
Code behind:
namespace UWP.Learning
{
using Windows.UI.Xaml.Controls;
public sealed partial class MainPage : Page
{
public MainPage() { this.InitializeComponent(); }
public string MyPlaceHolder => "FOOBAR";
}
}
Looks like a bug to me. An easy workaround is to have a one-time check within the Loaded event.
Loaded += (s, e) =>
{
switch (ActualWidth)
{
case var w when (w >= 400 && w < 800):
VisualStateManager.GoToState(this, "SmallState", false);
break;
case var w when (w >= 800):
VisualStateManager.GoToState(this, "WideState", false);
break;
}
};

WPF Smoothly animated ProgressBar in template

I am working on an MVVM application and I would like to have a ProgressBar that smoothly animates to it's new value when that property changes. I have seen several answers to this question using c# but I'd prefer to do it all inside the template. The problem I'm having is setting up and targeting the event and storyboard properly. Here is what I have currently:
The progress bar-
The style- (just the triggers)
<ControlTemplate.Triggers>
<EventTrigger RoutedEvent="RangeBase.ValueChanged">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="???????"
Storyboard.TargetProperty="Value"
To="???????" Duration="0:0:5" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
I took the trigger code from here: http://msdn.microsoft.com/en-us/library/system.windows.controls.progressbar(v=vs.110).aspx.
How do I set the TargetName to the template itself so that it applies to all the controls which use this template? How do I set "To" to the incoming Value? There appears to be a way to grab the "Binding" value but I have Value and Max both bound on the progressbar element. How would it know what to use?
Here is the whole template for reference:
<Style x:Key="ProgressStyle" TargetType="{x:Type ProgressBar}">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ProgressBar}">
<Grid MinHeight="14" MinWidth="20">
<Border x:Name="BaseRectangle" Background="{StaticResource BaseColor}" CornerRadius="10,0,10,0"></Border>
<Border x:Name="GlassRectangle" CornerRadius="10,0,10,0" Background="{StaticResource GlassFX}" Panel.ZIndex="10"></Border>
<Border x:Name="animation" CornerRadius="10,0,10,0" Opacity=".7" Background="{Binding Path=Foreground, RelativeSource={RelativeSource TemplatedParent}}" HorizontalAlignment="Left"></Border>
<Border x:Name="PART_Indicator" CornerRadius="10,0,10,0" Background="{Binding Path=Foreground, RelativeSource={RelativeSource TemplatedParent}}" HorizontalAlignment="Left"></Border>
<Border x:Name="PART_Track" BorderThickness="1" CornerRadius="10,0,10,0" BorderBrush="Black"></Border>
<Border x:Name="BordeCabeceraSombra" BorderThickness="2" CornerRadius="10,0,10,0" BorderBrush="DarkGray" Opacity=".2" Margin="1,1,1,0"></Border>
<Label x:Name="Progress" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" FontWeight="Bold" Foreground="White" Opacity=".7" Content="{Binding Path=Value, RelativeSource={RelativeSource TemplatedParent}}"></Label>
</Grid>
<ControlTemplate.Triggers>
<EventTrigger RoutedEvent="RangeBase.ValueChanged">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="???????"
Storyboard.TargetProperty="Value"
From="???????" To="???????" Duration="0:0:5" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<Trigger Property="IsIndeterminate" Value="True">
<Setter Property="Visibility" TargetName="Progress" Value="Hidden"></Setter>
<Setter Property="Background" TargetName="PART_Indicator">
<Setter.Value>
<MultiBinding>
<MultiBinding.Converter>
<wintheme:ProgressBarHighlightConverter/>
</MultiBinding.Converter>
<Binding Source="{StaticResource GlowFXProgressAnimated}"/>
<Binding Path="ActualWidth" ElementName="BaseRectangle"/>
<Binding Path="ActualHeight" ElementName="BaseRectangle"/>
</MultiBinding>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value=".5"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Any help would be appreciated!
I think its better way.
You can create behavior to do this. (MVVM WPF)
Create class:
class ProgresBarAnimateBehavior : Behavior<ProgressBar>
{
bool _IsAnimating = false;
protected override void OnAttached()
{
base.OnAttached();
ProgressBar progressBar = this.AssociatedObject;
progressBar.ValueChanged += ProgressBar_ValueChanged;
}
private void ProgressBar_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (_IsAnimating)
return;
_IsAnimating = true;
DoubleAnimation doubleAnimation = new DoubleAnimation
(e.OldValue, e.NewValue, new Duration(TimeSpan.FromSeconds(0.3)), FillBehavior.Stop);
doubleAnimation.Completed += Db_Completed;
((ProgressBar)sender).BeginAnimation(ProgressBar.ValueProperty, doubleAnimation);
e.Handled = true;
}
private void Db_Completed(object sender, EventArgs e)
{
_IsAnimating = false;
}
protected override void OnDetaching()
{
base.OnDetaching();
ProgressBar progressBar = this.AssociatedObject;
progressBar.ValueChanged -= ProgressBar_ValueChanged;
}
}
And simply usage:
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:b="clr-namespace:YOURNAMESPACE.Behaviors"
<ProgressBar Height="7"
Value="{Binding LoadingValue}">
<i:Interaction.Behaviors>
<b:ProgresBarAnimateBehavior />
</i:Interaction.Behaviors>
</ProgressBar>
I never actually found a solution to this. I ended up just writing my own control. This isn't technically an answer to the question, but I figure I may as well post it. If someone is looking for an animating progress control for MVVM this may help.
namespace Card_System.Controls
{
/// <summary>
/// Interaction logic for StatProgressBar.xaml
/// </summary>
public partial class StatProgressBar : UserControl
{
private double _trackWidth;
private bool _isAnimate;
private bool _isRefresh;
public StatProgressBar()
{
InitializeComponent();
var descriptor = DependencyPropertyDescriptor.FromProperty(ActualWidthProperty, typeof(Border));
if (descriptor != null)
{
descriptor.AddValueChanged(TrackBorder, ActualWidth_ValueChanged);
}
}
public event PropertyChangedEventHandler PropertyChanged;
private double _barValueSet;
public double BarValueSet
{
get { return _barValueSet; }
set
{
_barValueSet = value;
OnPropertyChanged("BarValueSet");
_isAnimate = true;
AnimateWidth();
}
}
public double BarValueDesired
{
get { return (double)GetValue(BarValueProperty); }
set { SetValue(BarValueProperty, value); }
}
public static readonly DependencyProperty BarValueProperty =
DependencyProperty.Register("BarValueDesired", typeof(double), typeof(StatProgressBar), new UIPropertyMetadata(0.0d, new PropertyChangedCallback(BarValueDesired_PropertyChanged)));
public double BarMaximum
{
get { return (double)GetValue(BarMaximumProperty); }
set { SetValue(BarMaximumProperty, value); }
}
public static readonly DependencyProperty BarMaximumProperty =
DependencyProperty.Register("BarMaximum", typeof(double), typeof(StatProgressBar), new UIPropertyMetadata(0.0d));
public static void BarValueDesired_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
//Set BarValue to the value of BarValueDesired BEFORE it was just changed.
((StatProgressBar)d).BarValueSet = (double)e.OldValue;
}
public Brush BarColor
{
get { return (Brush)GetValue(BarColorProperty); }
set { SetValue(BarColorProperty, value); }
}
public static readonly DependencyProperty BarColorProperty =
DependencyProperty.Register("BarColor", typeof(Brush), typeof(StatProgressBar), new UIPropertyMetadata(Brushes.White, new PropertyChangedCallback(BarColor_PropertyChanged)));
public static void BarColor_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((StatProgressBar)d).BarFill.Background = (Brush)e.NewValue;
}
private void ActualWidth_ValueChanged(object a_sender, EventArgs a_e)
{
_trackWidth = TrackBorder.ActualWidth;
_isRefresh = true;
AnimateWidth();
}
public void AnimateWidth()
{
if (_isAnimate && _isRefresh)
{
double StartPoint = new double();
double EndPoint = new double();
double PercentEnd = new double();
double PercentStart = new double();
PercentStart = BarValueSet / BarMaximum;
StartPoint = _trackWidth * PercentStart;
PercentEnd = BarValueDesired / BarMaximum;
EndPoint = _trackWidth * PercentEnd;
DoubleAnimation animation = new DoubleAnimation(StartPoint, EndPoint, TimeSpan.FromSeconds(3));
this.BarFill.BeginAnimation(Border.WidthProperty, animation);
}
else return;
}
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
}
And here is the XAML:
<Grid>
<Grid MinHeight="14" MinWidth="20">
<Border x:Name="BaseRectangle" Background="{StaticResource BaseColor}" CornerRadius="0,0,0,0"/>
<Border x:Name="TrackBorder" BorderThickness="1" CornerRadius="0,0,0,0" BorderBrush="Black" Panel.ZIndex="20"/>
<Border x:Name="BarFill" HorizontalAlignment="Left" Opacity=".7" Background="White"/>
<Border x:Name="GlassOverlay" CornerRadius="0,0,0,0" Background="{StaticResource GlassFX}" Panel.ZIndex="10"/>
<Border x:Name="GlassOverlayBorder" BorderThickness="4" CornerRadius="0,0,0,0" BorderBrush="DarkGray" Opacity=".2" Panel.ZIndex="12"/>
</Grid>
I know this question is solved, but I found a really good implementation that doesn't require creating a UserControl. It imitates the "barber pole effect" and works right out of the box:
<SolidColorBrush x:Key="ProgressBarBorderBrush" Color="Transparent" />
<SolidColorBrush x:Key="ProgressBarBackgroundBrush" Color="White" />
<SolidColorBrush x:Key="ProgressBarTrackBackgroundBrush" Color="#63D055" />
<Style x:Key="{x:Type ProgressBar}" TargetType="{x:Type ProgressBar}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ProgressBar}">
<local:ClippingBorder x:Name="BorderBackground" CornerRadius="3" BorderThickness="0"
BorderBrush="{StaticResource ProgressBarBorderBrush}"
Background="{StaticResource ProgressBarBackgroundBrush}">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Determinate" />
<VisualState x:Name="Indeterminate" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="PART_Track" Margin="0" BorderThickness="0" CornerRadius="3" />
<Border x:Name="PART_Indicator" Margin="0" BorderThickness="0" CornerRadius="3" HorizontalAlignment="Left"
Background="{StaticResource ProgressBarTrackBackgroundBrush}" ClipToBounds="True">
<Border x:Name="DiagonalDecorator" Width="5000">
<Border.Background>
<DrawingBrush TileMode="Tile" Stretch="None" Viewbox="0,0,1,1" Viewport="0,0,36,34" ViewportUnits="Absolute">
<DrawingBrush.RelativeTransform>
<TranslateTransform X="0" Y="0" />
</DrawingBrush.RelativeTransform>
<DrawingBrush.Drawing>
<GeometryDrawing Brush="#48C739" Geometry="M0,0 18,0 36,34 18,34 Z" />
</DrawingBrush.Drawing>
</DrawingBrush>
</Border.Background>
<Border.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="(Border.Background).(DrawingBrush.RelativeTransform).(TranslateTransform.X)"
From="0" To=".36" RepeatBehavior="Forever" Duration="0:0:18" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Border.Triggers>
</Border>
</Border>
</Grid>
</local:ClippingBorder>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Simply edit speed and colors to your liking.

text highlighting animation in windows 8 apps

i want to create an animation where each word of a line changes its foreground color from black to white after some intervals.
initially all the words are set to black.
i have used this code:
DispatcherTimer text1timer = new DispatcherTimer();
text1timer.Interval = TimeSpan.FromMilliseconds(440);
text1timer.Tick += text1timer_Tick;
text1timer.Start();
void text1timer_Tick(object sender, object e)
{
text1timer.Tick -= text1timer_Tick;
txt1.Foreground = new SolidColorBrush(Colors.White);
text1timer.Stop();
text1timer.Tick += text2timer_Tick;
text1timer.Start();
}
private void text2timer_Tick(object sender, object e)
{
text1timer.Tick -= text2timer_Tick;
txt2.Foreground = new SolidColorBrush(Colors.White);
text1timer.Stop();
text1timer.Tick += text3timer_Tick;
text1timer.Start();
}
private void text3timer_Tick(object sender, object e)
{
text1timer.Tick -= text3timer_Tick;
txt3.Foreground = new SolidColorBrush(Colors.White);
text1timer.Stop();
text1timer.Tick += text4timer_Tick;
text1timer.Start();
}
and so on but i have more than 100 words and i will have to make more than 100 events of the timer.is there any other solution?
You can use StoryBoard for the desired functionality.Check the following codes.
<Page.Resources>
<Storyboard x:Name="TextForegroundSb" RepeatBehavior="Forever">
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Tag)" Storyboard.TargetName="textBlock">
<DiscreteObjectKeyFrame KeyTime="0:0:0.0" Value="Red"/>
<DiscreteObjectKeyFrame KeyTime="0:0:0.2" Value="Green"/>
<DiscreteObjectKeyFrame KeyTime="0:0:0.4" Value="Blue"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</Page.Resources>
Here is the Textblock
<TextBlock x:Name="textBlock" TextWrapping="Wrap" Text="TextBlock" FontSize="48" Tag="Red" FontWeight="Bold" Foreground="{Binding Tag, RelativeSource={RelativeSource Mode=Self}}" FontFamily="Global User Interface" />
Also you can modify the time by changing DiscreteObjectKeyFrame KeyTime property.
For playing the storyboard on a button click use this code.
xmlns:Interactivity="using:Microsoft.Xaml.Interactivity" <br/>
xmlns:Core="using:Microsoft.Xaml.Interactions.Core" <br/>
xmlns:Media="using:Microsoft.Xaml.Interactions.Media" <br/>
<Button Content="Start sb" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="915,285,0,0" Height="119" Width="276">
<Interactivity:Interaction.Behaviors>
<Core:EventTriggerBehavior EventName="Click">
<Media:ControlStoryboardAction Storyboard="{StaticResource TextForegroundSb}"/>
</Core:EventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
</Button>
Hope this helps.
Thanks..
Use storyboard! there are instructions online and on MSDN.

Visual States and a custom dependency property (MVVM)

I'm stuck trying to add a dependency property to a button. I have several buttons located in my header view and clicking on them changes the content in the ContentControl between different views. All this works great. I want the button that was clicked have a different forecolor than the others and it looks like I need to add a dependency property. I think I have all the pieces in place but can't figure out how to get them all to work together.
I have a string property named ViewState in my viewmodel which changes based upon the button being clicked. The property is changing and I'm calling RaisePropertyChanged when it happens. What do I need to do to bind the additional dependency property? I'm transitioning from the WinForm world and trying to mentally piece it all together but struggling a bit.
Here's what I have so far:
<Style TargetType="{x:Type Button}" x:Key="LocalButtonTemplate">
<Setter Property="Foreground" Value="White" />
<Setter Property="Background" Value="{x:Null}" />
<Setter Property="FontFamily" Value="Segoe UI" />
<Setter Property="FontSize" Value="18" />
<Setter Property="Cursor" Value="Hand" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="outerBorder" Background="{TemplateBinding Background}" Margin="4">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ViewState">
<VisualState x:Name="Dashboard">
<Storyboard>
<ColorAnimation Duration="0:0:0.1" To="Yellow"
Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)"
Storyboard.TargetName="contentPresenter"/>
</Storyboard>
</VisualState>
<VisualState x:Name="AccountTables">
<Storyboard>
<ColorAnimation Duration="0:0:0.1" To="Red"
Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)"
Storyboard.TargetName="contentPresenter"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Normal">
<Storyboard>
<ColorAnimation Duration="0:0:0.1" To="Purple"
Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)"
Storyboard.TargetName="contentPresenter"/>
</Storyboard>
</VisualState>
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Duration="0:0:0.1" To="#35A84D"
Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)"
Storyboard.TargetName="contentPresenter"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid>
<Border x:Name="Background" BorderBrush="Transparent">
<Grid>
<ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Margin="4,5,4,4"/>
</Grid>
</Border>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
My buttons:
<dxwuii:SplitPanel Margin="0,10,10,10" HorizontalAlignment="Right" Grid.Column="2" ItemSpacing="0" Orientation="Horizontal" ItemSizeMode="AutoSize" >
<Button Command="{Binding SendViewModelNameCommand, Mode=OneTime}" CommandParameter="AccountTablesViewModel" Style="{StaticResource LocalButtonTemplate}">Express Tables</Button>
<Button Command="{Binding SendViewModelNameCommand, Mode=OneTime}" CommandParameter="MappingViewModel" Style="{StaticResource LocalButtonTemplate}">Item Mapping</Button>
<Button Command="{Binding SendViewModelNameCommand, Mode=OneTime}" CommandParameter="ReportsViewModel" Style="{StaticResource LocalButtonTemplate}">Reports</Button>
<Button Command="{Binding SendViewModelNameCommand, Mode=OneTime}" CommandParameter="PostBalancesViewModel" Style="{StaticResource LocalButtonTemplate}">Post Balances</Button>
</dxwuii:SplitPanel>
Dependency Property Class:
namespace MyAppName.Model
{
public class StateManager : DependencyObject
{
public static string GetVisualStateProperty(DependencyObject obj)
{
return (string)obj.GetValue(VisualStatePropertyProperty);
}
public static void SetVisualStateProperty(DependencyObject obj, string value)
{
obj.SetValue(VisualStatePropertyProperty, value);
}
public static readonly DependencyProperty VisualStatePropertyProperty =
DependencyProperty.RegisterAttached(
"VisualStateProperty",
typeof(string),
typeof(StateManager),
new PropertyMetadata((dependencyObject, args) =>
{
var frameworkElement = dependencyObject as FrameworkElement;
if (frameworkElement == null)
return;
VisualStateManager.GoToState(frameworkElement, (string)args.NewValue, true);
}));
}
}
Set Tag and Attached property on your each button as below. Tag value will be the VisualState value to which button should go on click.
<Button Tag="AcountTables" local:StateManager.VisualStateProperty="{Binding YOURVIEWMODELPROPERTY}" Command="{Binding SendViewModelNameCommand, Mode=OneTime}" CommandParameter="AccountTablesViewModel" Style="{StaticResource LocalButtonTemplate}">Express Tables</Button>
Update your AttachedProperty like:
public static readonly DependencyProperty VisualStatePropertyProperty =
DependencyProperty.RegisterAttached(
"VisualStateProperty",
typeof(string),
typeof(StateManager),
new PropertyMetadata((dependencyObject, args) =>
{
var frameworkElement = dependencyObject as FrameworkElement;
if (frameworkElement == null)
return;
if (args.NewValue == frameworkElement.Tag.ToString())
{
VisualStateManager.GoToState(frameworkElement, (string)args.NewValue, true);
}
else
{
VisualStateManager.GoToState(frameworkElement, "Normal", true);
}
}));

How to stop an animation WPF?

How to stop an animation so it won't produce Completed event. Here's simple example
<Window x:Class="WpfApplication5.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="248" Width="318">
<Grid>
<Border Width="20" Height="20" Background="Red" MouseEnter="Border_MouseEnter" MouseLeave="Border_MouseLeave" x:Name="border" />
</Grid>
</Window>
And backing code:
private void Border_MouseEnter(object sender, MouseEventArgs e)
{
var a = new DoubleAnimation { To = 0, Duration = TimeSpan.FromMilliseconds(4000) };
a.Completed += (obj, args) => MessageBox.Show("Boom!");
border.BeginAnimation(Border.OpacityProperty, a);
}
private void Border_MouseLeave(object sender, MouseEventArgs e)
{
border.BeginAnimation(Border.OpacityProperty, null);
border.Opacity = 1;
}
If I move mouse out before rectangle becomes white it still will display popup window after some time. How to prevent this? Let's assume that Border_MouseLeave and Border_MouseEnter methods doesn't know about each other (they can't pass animation instance variable to each other).
you can use this:
<Border Width="20" Height="20" Background="Red" x:Name="border" >
<Border.Triggers>
<EventTrigger RoutedEvent="MouseEnter">
<BeginStoryboard Name="Ali">
<Storyboard>
<DoubleAnimation To="0" Duration="0:0:4" Completed="com" Storyboard.TargetProperty="Opacity"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeave">
<StopStoryboard BeginStoryboardName="Ali"/>
</EventTrigger>
</Border.Triggers>
</Border>
and :
private void com(object sender, EventArgs e)
{
MessageBox.Show("boom!");
}
You could use Property or Data Trigger's EnterActions and ExitActions properties or as #Ali said correctly use Begin and Stop storyboard.

Categories