Click here to Skip to main content
15,920,031 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
I've written some sample code to show a problem I'm experiencing. I need to move many (>>1000) objects around (all together) using the mouse, but it's really laggy and I'm trying to work out why.

This should run in a new WPF project, just need to name the grid "mainGrid" in the XAML:
C#
public partial class MainWindow : Window
{
    readonly TranslateTransform _translator = new TranslateTransform();
    readonly Canvas _canvas = new Canvas();

    public MainWindow()
    {
        InitializeComponent();

        Loaded += new RoutedEventHandler(MainWindow_Loaded);
        WindowState = System.Windows.WindowState.Maximized;
            
        _canvas.RenderTransform = _translator;
        mainGrid.Children.Add(_canvas);
    }

    void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        Ellipse ellipse;

        for (int x = 0; x < 40; x++)
        {
            for (int y = 0; y < 100; y++)
            {
                ellipse = new Ellipse();
                ellipse.Stroke = Brushes.Black;
                ellipse.StrokeThickness = 1;
                ellipse.Fill = Brushes.Green;
                ellipse.Width = ellipse.Height = 10;

                Canvas.SetLeft(ellipse, y * 15);
                Canvas.SetTop(ellipse, x * 15);
                _canvas.Children.Add(ellipse);
            }
        }
    }

    Point _dragPoint;

    protected override void OnMouseDown(System.Windows.Input.MouseButtonEventArgs e)
    {
        _dragPoint = e.GetPosition(this);
        CaptureMouse();

        base.OnMouseDown(e);
    }

    protected override void OnMouseMove(System.Windows.Input.MouseEventArgs e)
    {
        if (IsMouseCaptured)
        {
            Point newPosition = e.GetPosition(this);
            Vector dragVector = newPosition - _dragPoint;
            _dragPoint = newPosition;

            _translator.X += dragVector.X;
            _translator.Y += dragVector.Y;
        }

        base.OnMouseMove(e);
    }

    protected override void OnMouseUp(System.Windows.Input.MouseButtonEventArgs e)
    {
        ReleaseMouseCapture();

        base.OnMouseUp(e);
    }
}


I noticed that when you drag most of the ellipses of the side of the screen the whole thing speeds up so I'm guessing its related to rendering and there's nothing I can do stop this happening. Also if you comment out the stroke on the ellipses it runs much faster.

Any ideas? Thanks.
Posted
Updated 23-Aug-12 23:17pm
v3

From ScottGu's Blog[^]:

Massive performance wins are possible with the new Cached Composition feature in WPF 4, which allows applications to cache arbitrary content including live and fully-interactive controls, vector geometry, etc. as bitmaps which persist in video memory. Once cached, these elements can be arbitrarily transformed, animated, manipulated, and can have Effects applied, all without having to re-render the cached element.

This spares both the CPU and the GPU the cost of re-rendering content, and instead allows the GPU to render straight from the cache. The cache(s) understand dirty regions, so a blinking cursor in a cached textblock, for example, will only need to re-render the cursor between frames. There’s even a new Brush which specifically uses these intelligent caches – effectively a VisualBrush with vastly better performance.


A bit more on that here: New WPF Features: Cached Composition[^]


Best regards
Espen Harlinn
 
Share this answer
 
Comments
Kenneth Haugland 26-Aug-12 8:00am    
5'ed. Helps to know about stuff sometimes, no need to re-invent the wheel. :)
Espen Harlinn 26-Aug-12 8:08am    
Thank you, Kenneth :-D
OllyHayes 28-Aug-12 11:27am    
This is exactly what I wanted thanks!

All I did was add ellipse.CacheMode = new BitmapCache(); to implement.
Espen Harlinn 28-Aug-12 13:49pm    
Brilliant :-D
WPF was not designed to be a real time enviroment with lots of heavy manipulations. It has its limitations, and you should consider not to move so many objects around like this. One way to fix the issue is to make a bitmap of the elements you are about to move, and remove the selected elements from the Canvas, and when it drops them, simply add the objects again. Sorry but I cant really tell you why it dosent work, and what the limits are, as they might depende on the hardware configuration on your computer.

Good luck in any case :)
 
Share this answer
 
Comments
Espen Harlinn 26-Aug-12 7:57am    
As of version 4.0 WPF supports cached composition, speeding up this kind of stuff.
Kenneth Haugland 26-Aug-12 7:59am    
:laugh: So they have create a control after my specs? That actually sounds much better :)

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900