I have an MVVM pattern application where I want the users to be able to enter dates, but also apply some validation on those dates. I do this by checking whatever they enter and overwriting it with the nearest valid date, if their entry is not valid. In order to let the user know that their date has been overwritten, I would have tried to animate the foreground of the date picker textbox, but I find that the animation is only visible on the first time their date is "corrected" in this way.
In the MainViewModel, I have a Ping property that notifies the UI each time it is set to "true" and a validation method that sets Ping = true each time it has to overwrite a date:
public bool Ping
{
get => _ping;
set
{
if (value && !_ping)
{
_ping = value;
OnPropertyChanged();
_ping = false;
}
}
}
private DateTime _from;
//Bound to the Date input field in the UI
public DateTime From
{
get { return _from; }
set
{
if (_from != value)
{
_from = giveValidDate("From", value);
OnPropertyChanged();
}
}
}
private DateTime giveValidDate(string posn, DateTime givenDate)
{
DateTime validDate = new DateTime();
// [...A Load of validation that results in a valid Date output...] //
Ping = givenDate != validDate;
return validDate;
}
There is a TextBox style that I am using that has the animation on it:
<Style x:Key="PingableTextBox" TargetType="TextBox">
<Setter Property="TextBlock.FontSize" Value="18"/>
<Setter Property="TextElement.FontSize" Value="18"/>
<Setter Property="TextElement.Foreground" Value="{StaticResource Text_LightBrush}"/>
<Setter Property="TextElement.FontWeight" Value="Normal"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Border BorderThickness="{TemplateBinding Border.BorderThickness}"
CornerRadius="2"
BorderBrush="{StaticResource Highlight_LightBrush}"
Background="{StaticResource Empty_DarkBrush}"
x:Name="border"
SnapsToDevicePixels="True">
<ScrollViewer HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"
Name="PART_ContentHost" Focusable="False" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="UIElement.IsMouseOver" Value="True">
<Setter Property="Border.BorderBrush" TargetName="border" Value="{StaticResource Good_MidBrush}"/>
<Setter Property="Cursor" Value="IBeam"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding Ping}" Value="true">
<DataTrigger.EnterActions>
<StopStoryboard BeginStoryboardName="Pinger"/>
<BeginStoryboard Name="Pinger">
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="Foreground.Color"
From="{StaticResource Bad_Bright}" To="{StaticResource Text_Light}" FillBehavior="Stop"
Duration="0:0:0:1.0"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<RemoveStoryboard BeginStoryboardName="Pinger"/>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
However, when I run the application, the trigger is only seen to act once (the brief red flash when an invalid date is selected):
I have seen many other questions on Stack Overflow about the same issue, but the solution has always been to add the line <StopStoryboard BeginStoryboardName="Pinger"/> in the Enter Actions, to add the line <RemoveStoryboard BeginStoryboardName="Pinger"/> to the Exit Actions or to add FillBehavior="Stop" to the storyboard. I have tried every combination of each of these in all places I could think of and the problem still persists.
Is there some other explanation for the problem that I could have missed that would fix it for me, or something that I have failed to implement correctly.. In short, why is it only firing once?
PS - some of the questions I have used to implement the code you see above:
WPF Storyboard only fires once
WPF Fade In / Out only runs once
WPF MultiDataTrigger on Tag property only firing once
WPF - problem with DataTrigger which work only once
You must raise the PropertyChanged after you reset the Ping property in order to trigger the Trigger.ExitAction.
Setting the backing field _ping does not propagate any change notification to the view.
This means your problem is not the problem that your quoted answer tries to solve.
You should also not define the Trigger.ExitAction in your scenario. Since you have configured the animation to stop automatically once the timeline has completed (FillBehavior="Stop"), you don't need to do anything to stop it. Note that RemoveStoryboard does not do you any favor in your case. It would only complicate the logic to reset the property since RemoveStoryboard would kill the animation immediately on the instant property toggle. This means, avoiding the Trigger.ExitAction or to be more precise the RemoveStoryboard allows you to toggle the property instantly:
// Trigger the animation
Ping = givenDate != validDate;
// Reset the property immediately to reset the animation trigger.
// Because the `Trigger.ExitAction` is deleted,
// the currently running animation will complete the timeline.
Ping = false;
If you want to implement the logic more gracefully you can toggle the Ping property and define the Trigger.EnterAction for the true state and the Trigger.ExitAction for the false state (thus converting each state into a validation error signal):
public bool Ping
{
get => _ping;
set
{
if (value && !_ping)
{
_ping = value;
OnPropertyChanged();
}
}
}
private DateTime giveValidDate(string posn, DateTime givenDate)
{
DateTime validDate = new DateTime();
// [...A Load of validation that results in a valid Date output...] //
// Trigger the animation by toggling the property.
if (givenDate != validDate)
{
Ping ^= true;
}
return validDate;
}
<DataTrigger Binding="{Binding Ping}" Value="true">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="Foreground.Color"
From="{StaticResource Bad_Bright}" To="{StaticResource Text_Light}" FillBehavior="Stop"
Duration="0:0:0:1.0"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="Foreground.Color"
From="{StaticResource Bad_Bright}" To="{StaticResource Text_Light}" FillBehavior="Stop"
Duration="0:0:0:1.0"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
Related
I am binding a ListBox to a List in the ViewModel named FilmeSerienListe. SelectedItem is set when ismouseover = True. The SelectedItem of the ListBox is bound to a Property in the ViewModel named SelectedFilmSerie.
This means when the mouse is over a particular ListBoxItem, this ListBoxItem is selected and its value bound to SelectedFilmSerie. BUT this does not seem to work very well, because the SelectedFilmSerie Property is for some reason always NULL. So, I debugged the App to see what did go wrong – Now the weird behaviour – SelectedFilmSerie is in fact NOT the WHOLE time NULL.
At first – when the mouse is over a ListBoxItem – the value parameter is set to the right Object, and it is NOT NULL, BUT then when I go further with my debugging this SelectedFilmSerie Property is recalled and NOW the value parameter is NULL, which make the SelectedFilmSerie Property also NULL.
WPF:
<ListBox ItemsSource="{Binding FilmeSerienListe}"
SelectedItem="{Binding SelectedFilmSerie}">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<ContentPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver"
Value="True">
<Setter Property="IsSelected"
Value="true" />
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
C#
private IEnumerable<FilmeSerien> _filmeSerienListe;
public IEnumerable<FilmeSerien> FilmeSerienListe
{
get => _filmeSerienListe;
set
{
_filmeSerienListe = value;
NotifyPropertyChanged();
}
}
private FilmeSerien _selectedFilmSerie;
public FilmeSerien SelectedFilmSerie
{
get => _selectedFilmSerie;
set
{
Trace.WriteLine(value != null ? "Value is NOT null" : "Value is NULL");
_selectedFilmSerie = value;
NotifyPropertyChanged();
}
}
Debugger:
ismouseover = True:
4xStep Over:
1xStep Over:
4xStep Over:
Output:
The sec the mouse entered the ListBoxItem, I get Value is NOT null and the sec the mouse leaves the ListBoxItem, I get Value is NULL
More details:
The ListBox is a list of cards bound to FilmeSerienListe with the datatype IEnumerable<FilmeSerien> each ListBoxItem is a card which is a representation of a FilmeSerien.
A card contains several Properties that are in a Property with the datatype FilmeSerien. Like: Titel, Img, Vote and other. Vote is an int datatype Property.
Looks something like this:
Problem:
Every Time I hit a star to vote a movie. I get a NullReferenceException because the SelectedFilmSerie is null.
WPF For star:
<Viewbox>
<materialDesign:RatingBar Value="{Binding Vote}"
Orientation="Horizontal"
Foreground="SkyBlue"/>
</Viewbox>
If I understand you correctly, you need to select the ListBox element not by clicking, but by hovering the mouse over it.
To be honest, it does not even occur to my head for what this might be needed.
I asked in the comments to clarify the purpose of such an implementation, but you didn't answer.
But if, I understood your question correctly, then it is implemented like this:
<Window.Resources>
<Style x:Key="listBoxItemStyle" TargetType="ListBoxItem">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="IsSelected">
<DiscreteBooleanKeyFrame KeyTime="0" Value="True"/>
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid VerticalAlignment="Center" >
<ListBox ItemsSource="{Binding FilmeSerienListe}"
SelectedItem="{Binding SelectedFilmSerie}"
ItemContainerStyle="{DynamicResource listBoxItemStyle}">
</ListBox>
</Grid>
This question already has an answer here:
: 'Cannot animate 'Fill.Color' on an immutable object instance.'
(1 answer)
Closed 2 years ago.
I am new to WPF, I Have a rectangle that I try to animate to flesh red color if some boolean is true. and I want it to stop when the boolean is false. In order to do that, I used the <DataTrigger.ExitActions>
However, I still want my Fill color to change according to the AlertColor, but after the animation is stopped it seems like the binding is stoped also, and the background-color stays LightPink only.
why? how can I fix this and is there a better approach to animate the color only in case of a specific color and stop the animation when the color changes (with Binding)?
The XAML relevant code:
<Rectangle Width="840" Height="40">
<Rectangle.Style>
<Style TargetType="Rectangle">
<Setter Property="Fill">
<Setter.Value>
<SolidColorBrush Color="{Binding AlertUnit.AlertColor , FallbackValue=LightPink}"/>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding AlertUnit.Emergency}" Value="true" >
<DataTrigger.EnterActions>
<BeginStoryboard Name="FlashingRedAnimation">
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="Fill.Color" To="White" Duration="0:0:1" AutoReverse="True"
RepeatBehavior="Forever"></ColorAnimation>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="FlashingRedAnimation" />
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
edit:
I found the problem it was a really silly one. the binding should be:
Binding AlertUnit.AlertColor.Color
not:
Binding AlertUnit.AlertColor
Thank you all for the help.
I produced a similar visual effect by animating the opacitity value of a brush rather than the colour.
<Style TargetType="{x:Type vctrl:perBlinkingBorder}">
<Style.Triggers>
<Trigger Property="IsBlinking" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard TargetProperty="(BlinkingBorderBrush).Opacity">
<DoubleAnimation
AutoReverse="True"
RepeatBehavior="Forever"
From="1"
To="0"
Duration="0:0:0.5">
</DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</Style.Triggers>
</Style>
To ensure that the visual effect is removed, I have two brush properties on the perBlinkingBorder control, and switch between them when the IsBlinking property is set.
More details and a demo project on my recent blog post.
I found the problem it was a really silly one.
the binding should be:
Binding AlertUnit.AlertColor.Color
not:
Binding AlertUnit.AlertColor
Thank you all for the help.
I have a TabControl with dynamically created TabItems that each contain a Border element that I need to animate (make the border flash Yellow to orange) when a property on a viewmodel is greater than zero, via Data Binding, but remain black if the value is zero. Each TabItem has it's own instance of the viewmodel, so the property value could be different for each TabItem, therefore the animation should only be activated on the appropriate TabItem (i.e. each TabItem is a UserControl that contains several Border elements, one of which I wish to animate triggered by a Property value in the UserControls viewmodel).
I have several similar elements, so I am using a MultiDataTrigger to check for a tag on the element, as well as check the property value (via a converter).
I can successfully animate the BorderBrush when selecting a TabItem where the property value is greater than zero, but when I then select a TabItem where the property value is equal to zero, the animation should stop, but does not. I am also changing the BorderThickness and the Margin, and these settings return to the normal settings as expected, but the animation does not stop.
I am using a Style.Trigger to apply the animation, and a converter to convert the property's value from an int to a boolean (true if greater than zero, and false if zero).
Here is my xaml code (from app.xaml):
<Style TargetType="{x:Type Border}" x:Key="JobFilterExternalBorder">
<Setter Property="BorderThickness" Value="3"/>
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="CornerRadius" Value="3"/>
<Setter Property="Margin" Value="2,0,1,0.8"/>
<Style.Triggers>
<!-- Add Data Trigger to identify if filter is UnprocessedParts and value is > 0, and animate border to imitate a flashing border -->
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=Tag}" Value="IsUnprocessed"/>
<Condition Binding="{Binding UnprocessedQty, Converter={StaticResource ConvertNonZeroToBoolean}}" Value="true"/>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="BorderThickness" Value="6"/>
<Setter Property="Margin" Value="0,-2,-1,-1.2"/>
</MultiDataTrigger.Setters>
<MultiDataTrigger.EnterActions>
<BeginStoryboard Name="FlashStoryboard" Storyboard="{StaticResource AnimationFlashYellowToOrange}">
</BeginStoryboard>
</MultiDataTrigger.EnterActions>
<MultiDataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="FlashStoryBoard" />
<RemoveStoryboard BeginStoryboardName="FlashStoryBoard"/>
</MultiDataTrigger.ExitActions>
</MultiDataTrigger>
</Style.Triggers>
</Style>
And my Storyboard:
<Storyboard x:Key="AnimationFlashYellowToOrange" Storyboard.TargetProperty="BorderBrush" RepeatBehavior="Forever" Duration="0:0:1" FillBehavior="Stop">
<ObjectAnimationUsingKeyFrames>
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<SolidColorBrush Color="Yellow" />
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
<DiscreteObjectKeyFrame KeyTime="0:0:0.5">
<DiscreteObjectKeyFrame.Value>
<SolidColorBrush Color="Orange" />
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
And the view to which this is being applied:
<Border Name="UnprocessedQtyBorder" Tag="IsUnprocessed" Style="{StaticResource JobFilterExternalBorder}" >
</Border>
I can confirm that the MultiDataTrigger is working fine because the BorderThickness and changes back to the normal thickness when the MultiDataTrigger becomes false when selecting a TabItem where the property value is equal to zero. It's just the animation that does not stop.
I have tried:
Adding StopStoryboard to the MultiDataTrigger.ExitActions
Adding RemoveStoryboard to the MultiDataTrigger.ExitActions
Including FillBehaviour="Stop"
Adding a second MultiDataTrigger to start a new Storyboard that sets the BorderBrush to black
Changing the order of the Style settings to have the MultiDataTrigger before the standard property settings
Searching the internet for any other examples that might point me in the right direction
I need to have the Storyboard animate the border continuously while the offending element is on screen, so I have included the RepeatBehavior="Forever" property
I am following MVVM design pattern and would prefer to avoid having code-behind, but I'm not zealous about it.
I have been struggling with this all day and have not made any progress, so this is my last hope.
EDIT:
I suspect the MultiDataTrigger.ExitActions are never executed in order to stop the Storyboard, so an additional question must be asked; Is it even possible to stop a Storyboard in this manner? Can the MultiDataTrigger.ExitActions be triggered to execute some other way?
EDIT2:
I have created a sample VS solution to demonstrate the effect I am seeing. The solution can be found on GitHub here
EDIT3:
This is what is currently happening:
When returning to "Tab 1", the animation should stop.
I am working on a WPF application. I have a ToggleButton that is supposed to glow green when it is selected and flash a red glow when there is an error in the model the button is associated with. (It is an ObservableCollection<> ItemsControl). The animation works fine when the DataTrigger executes, but I want the animation to resume if I select the button then deselect it. In other words if there is an error associated with the buttons model (It is flashing red) and I select it (Now it is green) and then I deselect it then it should return to flashing red. What is actually happening is once the button is deselected it just maintains its red state without flashing. Here is my xaml.
<!-- This template is for the selection buttons on the left hand side of the application. -->
<ControlTemplate x:Key="SelectionControlTemplate" TargetType="{x:Type ToggleButton}">
<Grid Width="Auto" Height="Auto" Margin="3" >
<Rectangle x:Name="BaseLayer" HorizontalAlignment="Left" Height="50" RadiusY="8" RadiusX="8" Stroke="Black" StrokeThickness="1" VerticalAlignment="Top" Width="50" Fill="{DynamicResource FutureBlueButtonGradient}"/>
<Rectangle x:Name="GlowLayer" HorizontalAlignment="Left" Height="52.25" Width="52.25" RadiusY="6.5" RadiusX="6.5" Stroke="{x:Null}" StrokeThickness="1" VerticalAlignment="Top" Margin="-1.125"/>
<ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>
<!-- Animation for blinking. -->
<ControlTemplate.Resources>
<Storyboard x:Key="Storyboard1">
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)" Storyboard.TargetName="GlowLayer" RepeatBehavior="Forever">
<EasingColorKeyFrame KeyTime="0" Value="#FFFD0002"/>
<EasingColorKeyFrame KeyTime="0:0:0.5" Value="#3FFD0002"/>
<EasingColorKeyFrame KeyTime="0:0:1" Value="#FFFD0002"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</ControlTemplate.Resources>
<!-- Style Triggers -->
<ControlTemplate.Triggers>
<!-- ERROR CONDITION TRIGGER: Flashes a selection button glowing red when HasTripOrError property is set to true. -->
<DataTrigger Binding="{Binding HasTripOrError, UpdateSourceTrigger=PropertyChanged}" Value="True">
<Setter Property="Stroke" TargetName="GlowLayer" Value="{StaticResource SolidRedGlowBrush}"/>
<Setter Property="Effect" TargetName="GlowLayer">
<Setter.Value>
<BlurEffect/>
</Setter.Value>
</Setter>
<Setter Property="Fill" TargetName="GlowLayer" Value="{StaticResource RadialGradientRedGlowBrush}"/>
<DataTrigger.EnterActions>
<BeginStoryboard x:Name="ErrorGlowStoryBoard" Storyboard="{StaticResource Storyboard1}"/>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="ErrorGlowStoryBoard"/>
</DataTrigger.ExitActions>
</DataTrigger>
<!-- MOUSE OVER TRIGGER: Puts a white outline around the button and increases its brightness a little on mouse over. -->
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Stroke" TargetName="GlowLayer" Value="#FFFDFFFE"/>
<Setter Property="Fill" TargetName="BaseLayer" Value="{StaticResource FutureBlueButtonMouseOverGradient}"/>
</Trigger>
<!-- SELECTED TRIGGER: Makes the selected control glow green. -->
<Trigger Property="IsChecked" Value="True">
<Setter Property="Effect" TargetName="GlowLayer">
<Setter.Value>
<BlurEffect/>
</Setter.Value>
</Setter>
<Setter Property="Fill" TargetName="GlowLayer" Value="{StaticResource RadialGradientGreenGlowBrush}"/>
<Setter Property="Stroke" TargetName="GlowLayer" Value="{StaticResource SolidGreenGlowBrush}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
Here is the relevant code behind for the properties. Please note that I have tried to raise the property responsible for the animation once it moves to the deselected state.
public bool IsSelected
{
get { return _is_selected; }
set
{
if( _is_selected != value )
{
_is_selected = value;
RaisePropertyChangedEvent("IsSelected");
//We also need to raise the HasTripOrError property here to resume
//The red glow animation if there is an error.
RaisePropertyChangedEvent("HasTripOrError");
}
}
}
public bool HasTripOrError
{
get { return _has_error; }
set
{
if( value != _has_error)
{
_has_error = value;
RaisePropertyChangedEvent("HasTripOrError");
}
}
}
How do I restart the animation once IsSelected transitions to false.
Write your IsSelected Property as :
private bool _is_selected;
public bool IsSelected
{
get { return _is_selected; }
set
{
if (_is_selected != value)
{
_is_selected = value;
UpdateProperty("IsSelected");
//We also need to raise the HasTripOrError property here to resume
//The red glow animation if there is an error.
HasTripOrError = !HasTripOrError;
HasTripOrError = !HasTripOrError;
}
}
}
HasTripOrError is bound to a DataTrigger. So it will only execute when value of HasTripOrError will get changed.
HasTripOrError = !HasTripOrError;
HasTripOrError = !HasTripOrError;
above code insures that HasTripOrError value will restore to
original value at last and If any Binding is associated that will
get reflected.
i have the grid with storyboard as below.
<Grid x:Name="grd_Order" Grid.Column="2" Height="16" Margin="0,-2,0,0" Visibility="Collapsed" HorizontalAlignment="Center" VerticalAlignment="Center">
<Grid.Resources>
<Storyboard x:Key="stry_OrderMsgShowHide" RepeatBehavior="3x">
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Visibility)" >
<DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:2" Value="{x:Static Visibility.Collapsed}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</Grid.Resources>
<Grid.Style>
<Style >
<Style.Triggers>
<DataTrigger Value="True" Binding="{Binding Path=BlinkOrderAlert,Mode=TwoWay}">
<DataTrigger.EnterActions>
<BeginStoryboard x:Name="stry_BlinkOrdAlert" Storyboard="{StaticResource stry_OrderMsgShowHide}"/>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
and in my ViewModel.cs,
private bool blinkOrderAlert;
public bool BlinkOrderAlert
{
get
{
return blinkOrderAlert;
}
set
{
if (blinkOrderAlert == value)
return;
this.blinkOrderAlert = value;
this.RaisePropertyChanged(this, new PropertyChangedEventArgs("BlinkOrderAlert"));
}
}
public void BlinkOrdAlert()
{
this.BlinkOrderAlert=false;
this.BlinkOrderAlert = true;
}
public ViewModel()
{
this.BlinkOrderAlert=true;
}
and it only works first time when constructor is initialized. Whenever i call the BlinkOrdAlert function, it's not working anymore. How can i modify the datatrigger to run storyboard everytime i call the function? Thanks.
Consider adding the following data trigger to you style.
The Following data trigger will remove the story board when the BlinkOrderAlert value set to false and when the value was true it will add story board.
hope this will help.
<DataTrigger Value="False" Binding="{Binding Path=BlinkOrderAlert,Mode=TwoWay}">
<DataTrigger.EnterActions>
<RemoveStoryboard BeginStoryboardName="stry_BlinkOrdAlert"></RemoveStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
You should not really use a DataTrigger for this at all, you try use a property like an event which is quite a hack. Unfortunately the native triggers are, let's say not optimal, so you cannot use an EventTrigger as it only supports RoutedEvents.
But you might be able to use ViewModel-events using the EventTrigger from Blend's Interactivity (Blend 3 SDK) instead, so that might be worth a try.