I am developing a desktop application on WinUI 3. My task is to play a fade animation on a TextBlock (smoothly lower the opacity to zero), then perform some action (for example, change the text), and then play an appearance animation on the same TextBlock (smoothly increase the opacity to one). I need to do the steps in that order, but I'm having trouble.
// The code for creating and setting up animations has been omitted for brevity.
myAnimation1.InsertKeyFrame(0, 1);
myAnimation1.InsertKeyFrame(1, 0);
_TextBlock.StartAnimation(myAnimation1);
_TextBlock.Inlines.Clear();
_TextBlock.Inlines.Add(GetTextInline(phrase));
myAnimation2.InsertKeyFrame(0, 1);
myAnimation2.InsertKeyFrame(1, 0);
_TextBlock.StartAnimation(myAnimation2);
In this case, as soon as the first animation is played, the text immediately changes and then its smooth appearance follows. In other words, the first animation does not play. She doesn't make it. Previously, I worked with WPF and there was a special event that fired after the end of the animation, thanks to which it was possible to build chains of animations. But in WinUI 3, I did not find such events. If anyone knows how to do this, please write. However, I did not give up and decided to mimic this behavior using the Task class in this way.
// The code for creating and setting up animations has been omitted for brevity.
Task task1 = new Task(() =>
{
myAnimation1.InsertKeyFrame(0, 1);
myAnimation1.InsertKeyFrame(1, 0);
_TextBlock.StartAnimation(myAnimation1);
});
Task task2 = task1.ContinueWith((Task task) =>
{
_TextBlock.Inlines.Clear();
_TextBlock.Inlines.Add(GetTextInline(phrase));
});
Task task3 = task2.ContinueWith((Task task) =>
{
myAnimation2.InsertKeyFrame(0, 1);
myAnimation2.InsertKeyFrame(1, 0);
_TextBlock.StartAnimation(myAnimation2);
});
task1.Start();
task3.Wait();
But this code ends with an exception at the line task3.Wait(); "System.AggregateException: "One or more errors occurred. (The application accessed an interface related to another thread. (0x8001010E (RPC_E_WRONG_THREAD)))""
I tried to remove this line, but these three tasks did not run at all. At the moment I have run out of ideas how I can solve this problem and implement what I have in mind. But I am sure that there is a solution, because this framework has a lot of possibilities for working with animation. Help me please.
The error means you're calling UI technology on a thread that's not the UI thread.
You can do this using a ScopedBatch, with an extension method, something like this:
public static CompositionScopedBatch RunScopedBatch(
this Compositor compositor,
Action action,
Action onCompleted = null,
CompositionBatchTypes types = CompositionBatchTypes.Animation)
{
if (compositor == null)
throw new ArgumentNullException(nameof(compositor));
if (action == null)
throw new ArgumentNullException(nameof(action));
var batch = compositor.CreateScopedBatch(types);
if (onCompleted != null)
{
// note: if Completed finishes too soon
// it means there was an exception, problem, etc.
batch.Completed += (s, e) => onCompleted();
}
try
{
action();
}
finally
{
batch.End();
}
return batch;
}