Reputation:
I'm using C# WPF and Blend for Visual Studio 2019. I have a button that will get data from a SQL Server database on click.
Also, the button has an animation in Blend that will run rotate OnPreviewMouseDown
.
But the problem is when I click the button in one-moment animation is running but then it suddenly stops.
I think this problem is because of the button on Click
event running some code and that prevents the animation from continuing.
Long story short: the animation for the button appears to not working when click event is processing.
XAML :
<Window.Resources>
<Storyboard x:Key="RotationBtn">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)" Storyboard.TargetName="Command4">
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="720"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<Window.Triggers>
<EventTrigger RoutedEvent="UIElement.PreviewMouseDown" SourceName="Command4">
<BeginStoryboard x:Name="RotationBtn_BeginStoryboard" Storyboard="{StaticResource RotationBtn}"/>
</EventTrigger>
</Window.Triggers>
<Grid>
<Button x:Name="Command4" Content="Next Stage" Margin="599,406,304,84" Width="130" Height="37" FontSize="8" Click="Command4_Click" Background="#FFDDDDDD" BorderBrush="{x:Null}" RenderTransformOrigin="0.5,0.5">
<Button.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Button.RenderTransform>
</Button>
</Grid>
CS Code:
private void Command4_Click(object sender, RoutedEventArgs e)
{
var MyQuery = dbms.Database.SqlQuery<DB_Cust>("SELECT * FROM Customers").ToList();
}
What have I tried :
First Try
private void Command4_Click(object sender, RoutedEventArgs e)
{
Thread trd = new Thread(() =>
{
Dispatcher.Invoke((Action)(() =>
{
Storyboard sb = TryFindResource("RotationBtn") as Storyboard;
Storyboard.SetTarget(sb, Command4 );
sb.Begin();
}));
});
var MyQuery = dbms.Database.SqlQuery<DB_Cust>("SELECT * FROM Customers").ToList();
}
Second Try
private void Command4_Click(object sender, RoutedEventArgs e)
{
new Thread(() =>
{
App.Current.Dispatcher.Invoke((Action)delegate
{
Storyboard sb = TryFindResource("RotationBtn") as Storyboard;
Storyboard.SetTarget(sb, Command4);
sb.Begin();
});
}).Start();
var MyQuery = dbms.Database.SqlQuery<DB_Cust>("SELECT * FROM Customers").ToList();
}
Upvotes: 0
Views: 350
Reputation:
Try this :
private void Command4_Click(object sender, RoutedEventArgs e)
{
BackgroundWorker bgWorker = new BackgroundWorker ();
bgWorker.DoWorker += DoWorkEventHandler(bgWorker_DoWork);
}
Private void bgWorker_DoWork(object sender, DoWorkEvent)
{
Storyboard sb = TryFindResource("RotationBtn") as Storyboard;
//Storyboard.SetTarget(sb, ButtonRotate);
sb.Begin();
}
Upvotes: 0
Reputation: 7943
First, you forgot to start the thread:
private void Command4_Click(object sender, RoutedEventArgs e)
{
Thread trd = new Thread(() =>
{
Dispatcher.Invoke((Action)(() =>
{
Storyboard sb = TryFindResource("RotationBtn") as Storyboard;
Storyboard.SetTarget(sb, Command4);
sb.Begin();
}));
});
trd.Start();
}
Secondly, your animation starts from the current value of the rotation angle and continues up to 720 degrees.
But when you start the animation again, the angle is already equal to 720 and its animation to 720, accordingly, does not occur.
To start the animation from zero again, you need to set the first frame from zero.
<Storyboard x:Key="RotationBtn">
<DoubleAnimationUsingKeyFrames
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)"
Storyboard.TargetName="Command4">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="720"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
But I would rather use a linear animation with relative displacement rather than frame-by-frame.
If, of course, this is acceptable for your task.
<Storyboard x:Key="RotationBtn">
<DoubleAnimation
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)"
Storyboard.TargetName="Command4"
By="720"/>
</Storyboard>
Thirdly, classes "Storyboard", "BeginStoryboard" and others are designed to make it easy to run animations from XAML.
When launched from Sharpe, they are not required.
Of course, they can be used in Sharpe, but there is little sense in this.
Also, in modern Sharp, the explicit creation of new flows is not accepted (only in very rare cases). Tasks are used for asynchronous execution.
<Window ---------------------------
---------------------------
---------------------------
Height="600" Width="1700">
<Window.Resources>
<DoubleAnimation x:Key="Button.Rotate.Animation" By="720"/>
</Window.Resources>
<Grid>
<Button x:Name="Command4" Content="Next Stage" Margin="599,406,304,84"
Width="130" Height="37" FontSize="8" Click="Command4_Click"
Background="#FFDDDDDD" BorderBrush="{x:Null}"
RenderTransformOrigin="0.5,0.5">
<Button.RenderTransform>
<RotateTransform x:Name="ButtonRotate"/>
</Button.RenderTransform>
</Button>
</Grid>
</Window>
private void Command4_Click(object sender, RoutedEventArgs e)
{
Task.Run(() =>
{
Dispatcher.Invoke((Action)(() =>
{
var animation = TryFindResource("Button.Rotate.Animation") as AnimationTimeline;
ButtonRotate.BeginAnimation(RotateTransform.AngleProperty, animation);
}));
});
}
Fourth, you have an unnecessary target element assignment in the clicker.
The target is already specified in the XAML when the StoryBoard is declared.
Also notice the double call of the animation.
The first time a key is pressed, the trigger animation is invoked in XAML.
The second time the key is released, the clicker animation is called.
<Window.Resources>
<Storyboard x:Key="RotationBtn">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Angle" Storyboard.TargetName="ButtonRotate">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="720"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<Window.Triggers>
<EventTrigger RoutedEvent="UIElement.PreviewMouseDown" SourceName="Command4">
<BeginStoryboard x:Name="RotationBtn_BeginStoryboard" Storyboard="{StaticResource RotationBtn}"/>
</EventTrigger>
</Window.Triggers>
<Grid>
<Button x:Name="Command4" Content="Next Stage"
Margin="599,406,304,84"
Width="130" Height="37" FontSize="8"
Click="Command4_Click" Background="#FFDDDDDD"
BorderBrush="{x:Null}"
RenderTransformOrigin="0.5,0.5">
<Button.RenderTransform>
<RotateTransform x:Name="ButtonRotate"/>
</Button.RenderTransform>
</Button>
</Grid>
</Window>
private void Command4_Click(object sender, RoutedEventArgs e)
{
new Thread(() =>
{
Dispatcher.Invoke((Action)delegate
{
Storyboard sb = TryFindResource("RotationBtn") as Storyboard;
//Storyboard.SetTarget(sb, ButtonRotate);
sb.Begin();
});
}).Start();
}
P.S. I didn't see your "Second Try". This is due to my carelessness.
My apologies to you.
But the rest of the points in my answer remain relevant.
Upvotes: 1