WPF custom animation thread

Daniel Santos 20 Reputation points
2023-09-16T17:21:29.6333333+00:00

Hello,

I have a small simple WPF application (I am learing by doing).

I made some custom drawing on a Canvas declared in XAML, by using code in the corresponding C# file.

Now I want to access the canvas from another thread to be able to apply geometric transformations to it and its contents.

But because the main thread owns the Canvas object, I cannot assign transformations to it.

Is there a specific way of being able to change the Canvas from other threads ?

Thanks,

Regards

Developer technologies Windows Presentation Foundation
Windows for business Windows Client for IT Pros User experience Other
Developer technologies .NET Other
{count} votes

Accepted answer
  1. Hui Liu-MSFT 48,676 Reputation points Microsoft External Staff
    2023-09-18T02:10:47.7033333+00:00

    Hi,@Daniel Santos . Welcome Microsoft Q&A. To access the canvas from another thread to be able to apply geometric transformations to it and its contents, you can try referring to the following code. If you still face the problem, please share with me the complete code that can reproduce your problem to analyze.

    xaml:

      <StackPanel>
           
            <Canvas Name="canvas" Height="200">
                <!--<Path x:Name="path" Stroke="Black" StrokeThickness="1" Data="19 39 ,20 60,"  Fill="Black" />-->
                <Polygon Points="15.3 19 10.2 8 0, 19 0.2, 18 10.3 1" Fill="Navy"></Polygon>
    
            </Canvas>
            <Button x:Name="btn" Content="thread" Click="btn_Click"/>
        </StackPanel>
    

    codebedhind:

    
     public partial class MainWindow : Window
        { 
            private Dispatcher uiDispatcher = Dispatcher.CurrentDispatcher;
    
            public MainWindow()
            {
                InitializeComponent();
            }
            void ApplyTransformationFromAnotherThread()
            {
                ScaleTransform scaleTransform = new ScaleTransform(2.0, 2.0);
    
               
                uiDispatcher.Invoke(() =>
                {
                   
                    Canvas myCanvas = canvas; 
    
                   
                    myCanvas.RenderTransform = scaleTransform;
                });
            }
    
            private void btn_Click(object sender, RoutedEventArgs e)
            {
                ApplyTransformationFromAnotherThread();
            }
        }
    
    

    Update:

    
     private int originX = 50;
            private int originY = 50;
            private int incrementX = 20;
            private int incrementY = 20;
            private int countX = 7;
            private int countY = 7;
            private int currentAngle = 0;
            private int rotateIncrement = 10;
            private RotateTransform rotateTransform;
    
            public MainWindow()
            {
                InitializeComponent();
    
                // Create and configure your canvas on the UI thread
                Canvas canvas = drawboard;
                rotateTransform = new RotateTransform();
                rotateTransform.CenterX = originX + 4 * incrementX;
                rotateTransform.CenterY = originY + 4 * incrementY;
                canvas.RenderTransform = rotateTransform;
    
                for (int xindex = 0; xindex < countX; xindex++)
                {
                    for (int yindex = 0; yindex < countY; yindex++)
                    {
                        Control cross11 = new Control();
                        cross11.Template = (ControlTemplate)canvas.FindResource("crosshairs");
                        Canvas.SetTop(cross11, originY + yindex * incrementY);
                        Canvas.SetLeft(cross11, originX + xindex * incrementX);
                        canvas.Children.Add(cross11);
                        cross11.Name = "cross_" + xindex + "_" + yindex;
                    }
                }
    
                // Start a DispatcherTimer to update the rotation
                DispatcherTimer timer = new DispatcherTimer();
                timer.Interval = TimeSpan.FromMilliseconds(100); // Adjust the update interval as needed
                timer.Tick += Timer_Tick;
                timer.Start();
            }
    
            private void Timer_Tick(object sender, EventArgs e)
            {
                // Update the rotation angle on each tick
                currentAngle += rotateIncrement;
                rotateTransform.Angle = currentAngle;
            }
    

    The result:

    enter image description here


    If the response is helpful, please click "Accept Answer" and upvote it.

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.