UserControl neu zeichnen lassen

  • WPF

Es gibt 4 Antworten in diesem Thema. Der letzte Beitrag () ist von Chris213.

    UserControl neu zeichnen lassen

    Hi,

    ich bin schon den ganzen Tag daran, mein UserControl neu zeichnen zulassen, sodass die geänderten Werte sichtbar werden. Dafür habe ich jedoch nichts passendes gefunden, was mir weiterhilft. Bei Windows Forms konnte ich dies ganz einfach mit einem Aufruf von .Refresh erreichen, wie kann ich das in WPF erreichen.
    Wenn Du für Deine Application ein vernünftiges Design verwendest, so brauchst Du Refresh weder in Forms noch in WPF.

    Ansonsten kannst Du mit dem uiElement.Dispatcher.Invoke ein ähnliches Ergebnis erzielen wie mit dem Control.Refresh.

    @Artentus InvalidateVisual ist wie das Control.Invalidate asynchron (d.h. der GUI-Thread muss erstmal seine Messages verarbeiten können) , während das Refresh ein sofortiges Neuzeichnen bewirkt. Aber vielleicht reicht es dem TE ja aus.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Kangaroo“ ()

    Spoiler anzeigen
    So, ich habe nun versucht beide Varianten anzuwenden.

    Variante 1: InvalidateVisual
    Lässt das Control neu zeichnen jedoch nicht jedes mal, wenn ein neuer Punkt hinzugefügt wird sonder erst ganz am Ende. Das wolltest du sagen Kangaroo, oder?


    Variante 2: Dispatcher.Invoke
    Habe ich versucht anzuwenden, habe es aber nicht hinbekommen. Siehe Code.


    VB.NET-Quellcode

    1. Public Function addPunkt(p As Punkt, Optional teil As Boolean = False) As Boolean 'Ausgangsfunktion, sie soll ein neu zeichnen auslösen
    2. skalierungAnpassen(p)
    3. If p.Y > _maxPunkt.Y Then
    4. _maxPunkt = p
    5. End If
    6. hauptgraph.addPunkt(p)
    7. ' Me.InvalidateVisual()
    8. Dim args() As Object = {}
    9. Me.Dispatcher.Invoke(New Action(AddressOf test), args)
    10. Return (True)
    11. End Function
    12. Public Sub test()
    13. Dim dv As New DrawingVisual()
    14. Dim dc As DrawingContext = dv.RenderOpen()
    15. neuZeichnen(dc)
    16. Me.AddVisualChild(dv)
    17. End Sub
    18. Protected Overrides Sub OnRender(drawingContext As System.Windows.Media.DrawingContext)
    19. MyBase.OnRender(drawingContext)
    20. neuZeichnen(drawingContext)
    21. End Sub
    22. Public Sub neuZeichnen(dc As System.Windows.Media.DrawingContext, Optional teil As Boolean = False)
    23. 'If teil = False Then
    24. ' dv.RenderOpen()
    25. 'End If
    26. If Me.Width > 0 And Height > 0 Then
    27. xAchse = getXAchsenHöhe()
    28. zeichneGrid(dc)
    29. zeichneX_Achse(dc)
    30. zeichneY_Achse(dc)
    31. zeichnePunkte(dc)
    32. zeichneMaxPunkt(dc)
    33. End If
    34. End Sub




    Sonst habe ich mir auch überlegt ob man das Problem auch mit einem Binding lösen kann. Wenn man ein Property von "Punkt" (eigene Punkt Klasse), mit einer Punkt Liste verbinden.



    So hab dann das Problem selbst lösen können, ist vielleicht nicht die sauberste Lösung aber es funktioniert für den Anfang. Hier die Lösung:

    Als erstes habe ich im Konstruktor der Klasse das Event "CompositionTarget.Rendering" an eine eigene Methode verbunden (AdHandler). Darin hab ich dann folgender Code gepackt

    VB.NET-Quellcode

    1. If hasChanges Then
    2. Me.RemoveVisualChild(dv)
    3. hasChanges = False
    4. dv = New DrawingVisual
    5. Using dc As DrawingContext = dv.RenderOpen()
    6. neuZeichnen(dc)
    7. End Using
    8. Me.AddVisualChild(dv)
    9. End If

    dv ist ein Objekt vom Typ DrawingVisual. Wenn ich nun das Diagramm neu zeichnen lassen möchte, muss ich nur hasChanges auf true setzten.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Chris213“ ()