Hi,
Thanks for the link.
Please find solution attached. Can't post code block because of the WAF2.
BR,
Adnan
This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
I'm using C# WPF and Blend for Visual Studio 2019 I have a button when user click on it it will get data from the SQL Server database
Also, a made Animation for this button in Blend that will run rotate animation OnPreviewMouseDown
But the problem is when I click the button in one-moment animation is running but suddenly stopped
I think this problem is because of the button on Click event running some code and that prevent to animation continue
Long story short: the animation for the button not working when event click is processin
in Blend :
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)
{
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();
}
Result of The result of the upper lines ↑ :
as you can see it stop
what I need is something like this simulated :
keep animation show when that's runnig this :
var MyQuery = dbms.Database.SqlQuery<DB_Cust>("SELECT * FROM Customers").ToList();
My Thread for animation does not work correctly it mean's when I click on the button
in a few moment animation will run but after In a short moment suddenly animation will stop until the code of query for get data from database in Click Event To end
how to fix this I want to show animation until code is processing in an event
Please help and thanks for taking your time for answer this question
Edit : When I use this code :
if(string.IsNullOrEmpty(MyTextBox))
{
//Do somthing
}
I Have This Error :
The calling thread cannot access this object because a different thread owns it
and Next I have tried This:
Dispatcher.Invoke(new Action(() =>
{
if (string.IsNullOrEmpty(MAH.Text))
{
//Do somthing
}
}));
but again my program will freeze or lock until process this :string.IsNullOrEmpty(MAH.Text)
and animation will stop
Please Help?
My Project Link :
kj8BXD2Q
in One Drive :
s!Aq2vCYipSlKYggAypH3MeVMIMV5I
Hi,
Thanks for the link.
Please find solution attached. Can't post code block because of the WAF2.
BR,
Adnan
In my opinion, to continue animation indefinitely until the database operation is finished, add an attribute:
<Storyboard x:Key="RotationBtn" RepeatBehavior="Forever">
Also remove the trigger because you will start the animation programmatically.
The lengthy database operation can be started as a background task. For example:
private void Command4_Click( object sender, RoutedEventArgs e )
{
// start the animation
{
Storyboard sb = (Storyboard)FindResource( "RotationBtn" );
Storyboard.SetTarget( sb, Command4 );
sb.Begin( );
}
// start the background database operation
var t = new Thread( ( ) =>
{
var MyQuery = dbms.Database.SqlQuery<DB_Cust>( "SELECT * FROM Customers" ).ToList( );
// stop the animation and display the results
App.Current.Dispatcher.Invoke( ( ) =>
{
Storyboard sb = (Storyboard)FindResource( "RotationBtn" );
sb.Stop( );
// . . .
} );
} )
{
IsBackground = true
};
t.Start( );
}
After finishing the database operation, you can stop the animation and access the elements (to display the results, for example) inside the Invoke block.
Hi,
There is a few problems with your code.
1) Threading
All code inside Command4_Click is executing in the main thread, including long running DB query execution.
private void Command4_Click(object sender, RoutedEventArgs e) {
// The new thread is created from the main thread.
new Thread(() =>
{
// Then delegate is invoked in the main thread.
App.Current.Dispatcher.Invoke((Action)delegate
{
// This code block is executing in the main thread.
Storyboard sb = TryFindResource("RotationBtn") as Storyboard;
Storyboard.SetTarget(sb, Command4);
sb.Begin();
});
}).Start();
// The long running operation in executing in the main thread.
var MyQuery = dbms.Database.SqlQuery<DB_Cust>("SELECT * FROM Customers").ToList();
}
2) Storyboard RepeatBehaviour
The storyboard animation will be played just once. In your case RepeatBehaviour property should be set to "Forever".
<Window.Resources>
<Storyboard x:Key="RotationBtn" RepeatBehavior="Forever">
3) EventTrigger
You are starting and stopping the animation manually and therefore event trigger should be removed.
Solution (based on your code):
XAML:
<Window.Resources>
<Storyboard x:Key="RotationBtn" RepeatBehavior="Forever">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)" Storyboard.TargetName="Command4">
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="720"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</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>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Button.RenderTransform>
</Button>
</Grid>
CS:
private async void Command4_Click(object sender, RoutedEventArgs e) {
// Get storyboard.
var storyboard = GetStoryboard();
// Start animation.
StartAnimation(storyboard, Command4);
// Get customers.
var customers = await GetCustomersAsync();
// TODO: Process result.
// Stop animation.
StopAnimation(storyboard);
}
private async Task<List<string>> GetCustomersAsync() {
// Simulate long running operation.
await Task.Delay(5000);
return new List<string> {
"Customer 1",
"Customer 2"
};
}
private Storyboard GetStoryboard()
{
return TryFindResource("RotationBtn") as Storyboard;
}
private void StartAnimation(Storyboard storyboard)
{
Storyboard.SetTarget(storyboard, Command4);
storyboard.Begin();
}
private void StopAnimation(Storyboard storyboard)
{
storyboard.Stop();
}
In general it will be better to utilize full potential of WPF and .NET framework.
BR,
Adnan
You begin the storyboard (at line 9 in CS Code) and never stop it, then this animation start and never stop until you close the application.
so you can Stop this animation on any event (eg: MouseLeave) :
private void Command4_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
{
new Thread(() =>
{
App.Current.Dispatcher.Invoke((Action)delegate
{
Storyboard sb = TryFindResource("RotationBtn") as Storyboard;
Storyboard.SetTarget(sb, Command4);
sb.Stop();
});
}).Start();
}