2012-04-03 4 views
11

Ich muss eine Menge Shape (etwa 1/2 hunderttausend) als [Canvas] [2] 's Kinder zeichnen. Ich mache das in meiner WPF-Anwendung, die Arbeit in zwei Teile teilt: Zuerst erstelle ich Formen, indem ich die Eigenschaften von jedem von ihnen (wie Rand, Fülle, Breite, usw.) einstelle, nachdem ich Formen als Canvas-Kinder hinzugefügt habe.Wie kann die Canvas-Renderleistung verbessert werden?

MyCanvas.Children.Add(MyShape) 

Jetzt möchte ich die Leistung des zweiten Teils verbessern, denn wenn ich die Formen zeichnen meine Anwendung für einen langen Zeitraum gesperrt wird. Also habe ich versucht, die Dispatcher und ihre Methode [BeginInvoke] [4] mit verschiedenen [Prioritäten] [5] zu verwenden: nur wenn ich die Hintergrund-Priorität die Hauptanwendung nicht blockiert, sonst bleibt die Anwendung blockiert und das "Bild" ist nicht angezeigt, bis alle Formen zu meinem Canvas hinzugefügt wurden, aber wenn ich die Hintergrundpriorität verwende, ist offensichtlich alles langsamer. Ich habe auch versucht, einen neuen Thread zu erstellen, anstatt den Dispatcher zu verwenden, aber es gab keine signifikante Änderung.

Wie kann ich dieses Problem beheben und generell die Leistung meiner Anwendung verbessern, wenn ich meine Shapes zu Canvas hinzufüge?

Danke.

+0

Haben Sie DrawingVisual ausprobiert? –

+0

Nein. Können Sie mir ein Beispiel dafür geben, wie Sie DrawingVisual anstelle einer Form wie Ellipse oder Pfad verwenden? Zum Beispiel, wie kann ich meinen Canvas [this] (http://msdn.microsoft.com/en-us/library/ms745546.aspx) Pfad mit DrawingVisual hinzufügen? – gliderkite

+0

Ja, es gibt einige tolle Informationen zu Google. Hier ist ein Link, mit dem Sie beginnen können: http://msdn.microsoft.com/en-us/magazine/dd483292.aspx –

Antwort

7

Benötigen Sie Visual Objekte anstelle von Shape; insbesondere, wie vorgeschlagen, DrawingVisual: ein visuelles Objekt, das zum Rendern von Vektorgrafiken verwendet werden kann. In der Tat, wie in der MSDN-Bibliothek geschrieben:

DrawingVisual ist eine einfache Zeichenklasse, die zum Rendern von Formen, Bildern oder Text verwendet wird. Diese Klasse wird als leicht eingestuft, da sie weder Layout-, Eingabe-, Fokus- oder Ereignisbehandlung bietet, was ihre Leistung verbessert. Aus diesem Grund sind Zeichnungen ideal für Hintergründe und Clip-Art.

So zum Beispiel eine DrawingVisual zu erstellen, die ein Rechteck enthält:

private DrawingVisual CreateDrawingVisualRectangle() 
{ 
    DrawingVisual drawingVisual = new DrawingVisual(); 

    // Retrieve the DrawingContext in order to create new drawing content. 
    DrawingContext drawingContext = drawingVisual.RenderOpen(); 

    // Create a rectangle and draw it in the DrawingContext. 
    Rect rect = new Rect(new System.Windows.Point(160, 100), new System.Windows.Size(320, 80)); 
    drawingContext.DrawRectangle(System.Windows.Media.Brushes.LightBlue, (System.Windows.Media.Pen)null, rect); 

    // Persist the drawing content. 
    drawingContext.Close(); 

    return drawingVisual; 
} 

Um DrawingVisual Objekte zu verwenden, benötigen Sie einen Host-Container für die Objekte zu erstellen. Das Hostcontainerobjekt muss von der FrameworkElement-Klasse abgeleitet sein, die die Unterstützung für die Layout- und Ereignisbehandlung bietet, die der DrawingVisual-Klasse fehlt. Wenn Sie ein Hostcontainerobjekt für visuelle Objekte erstellen, müssen Sie die visuellen Objektreferenzen in einem VisualCollection speichern.

public class MyVisualHost : FrameworkElement 
{ 
    // Create a collection of child visual objects. 
    private VisualCollection _children; 

    public MyVisualHost() 
    { 
     _children = new VisualCollection(this); 
     _children.Add(CreateDrawingVisualRectangle()); 

     // Add the event handler for MouseLeftButtonUp. 
     this.MouseLeftButtonUp += new System.Windows.Input.MouseButtonEventHandler(MyVisualHost_MouseLeftButtonUp); 
    } 
} 

Die Ereignisbehandlungsroutine kann dann durch Aufrufen der HitTest Methode Treffertest implementieren. Der HitTestResultCallback-Parameter der Methode verweist auf eine benutzerdefinierte Prozedur, mit der Sie die resultierende Aktion eines Treffertests ermitteln können.

+3

Es hilft, marginal, aber WPF ist nicht darauf ausgerichtet, 50.000 Visuals jeglicher Art zu behandeln. –

+0

Was ist also darauf ausgerichtet, hunderttausend Vektorgrafiken zu verarbeiten? – gliderkite

+0

Siehe Q und AI verknüpft mit: http://stackoverflow.com/questions/8713864/high-performance-graphics-using-the-wpf-visual-layer/8714107#8714107 –

1

Das ist viel von UIElements und wird wahrscheinlich nicht die Art von Leistung geben, die Sie suchen. Müssen Sie mit jedem der von Ihnen gerenderten Elemente interagieren können? Wenn nicht, würde ich dringend empfehlen, stattdessen WriteableBitmap zu verwenden. Wenn Sie Formen zeichnen müssen und nicht alle diese Logik selbst erstellen möchten (wer möchte das?), check out the WriteableBitmapEx project over on CodePlex.

+0

Ich muss mit allen Formen interagieren, auch ich verwende Shape, weil das "Bild" ein Vektorgrafikbild ist (Bild kann skaliert werden - mit Zoom - um jeden Betrag ohne Qualitätsverlust). Mit WritableBitmapEx könnte ich die gleichen Dinge tun? – gliderkite

+1

Ich würde Shape nicht verwenden, ich würde DrawingVisual verwenden. Können Sie diese Details bitte zu Ihrer Frage hinzufügen? Ich werde darüber nachdenken und meine Antwort überarbeiten. –

3

Vereinbart, dass, wenn Sie Millionen von Elementen zeichnen möchten, Sie es einfach nicht in WPF tun können. WriteableBitmapEx wie erwähnt ist eine gute Alternative.

Siehe this related question, die auf Hochleistungsgrafiken in WPF und die verfügbaren Alternativen eingehen.

Wenn Sie einfach Canvas verwenden müssen, überprüfen Sie diese ZoomableApplication2 - A million items. Dies ist eine Canvas-basierte Demo, die Virtualisierung stark nutzt, um eine vernünftige Leistung mit 1.000.000 UIElements auf einem Canvas zu erzielen.

+0

es ist möglich, weil ich etwa ein paar hunderttausend Elemente zeichnen muss (wie ich geschrieben habe) und ich benutze meine Antwort (es ist lange her, seit ich die Frage gestellt habe), trotzdem danke für deine Antwort, aber Bitmap ist keine Vektorgrafik. – gliderkite

1

Das mag etwas ohne Bezug sein, und ich entschuldige mich, wenn Sie so fühlen, aber in der Hoffnung, dass es etwas Licht für andere Benutzer geben kann, werde ich diesen Leckerbissen teilen.

Wir hatten einige Leistungsprobleme mit einem Canvas-Steuerelement zum Erfassen von Signaturen. Die Aufnahme war sehr gezackt und wir konnten keine gekrümmten Linien zeichnen. Es stellte sich heraus, dass es mit einem Stil verwandt war, der Schatten auf den UI-Elementen erzeugte. Durch Deaktivieren des Drop-Shadow-Effekts wurde unser Problem gelöst.

+0

Danke, ich hatte Probleme beim Zeichnen einer großen Anzahl von Zeilen in einem Raster, und durch Entfernen meines Schlagschatteneffekts gibt es keine Lag überhaupt! – Cyral

Verwandte Themen