.NET GUI

.NET Community rund um alle Graphical User Interface (GUI) Themen.
Willkommen bei .NET GUI. Anmeldung | Registrieren | Hilfe | Impressum | Forumsregeln
in Suchen

Eigene Linien in Grid Panel zeichnen

Letzter Beitrag 05-08-2008 10:28 von jpkleinau. 3 Antworten.
Seite 1 von 1 (4 Treffer)
Beiträge sortieren: Zurück Weiter
  • 05-07-2008 10:04

    • Benjamin Gopp
    • Top 50 Mitwirkender
      Männlich
    • Registriert am 04-21-2008
    • Lohmar - Germany
    • Beiträge 4
    • Punkte 80

    Eigene Linien in Grid Panel zeichnen

     

    Eigene Linien in Grid Panel zeichnen

     

     

    Das Grid ist das Mächtigste und am Häufigsten gebrauchte Panel in WPF.

    Mit der Eigenschaft „ShowGridLines“ lassen sich Hilfslinien anzeigen.

    <Grid ShowGridLines="True">

    Diese Linien dienen nur als Hilfestellung für den Entwickler, der so die Position der Spalten und Reihen erkennen kann.

    Leider kann man nicht selber bestimmen wie diese Linien aussehen. Oder etwas doch?

    Was passiert eigentlich im Grid wenn  ShowGridLines=True gesetzt wird?

    WPF-Controls können sich selbst zeichnen, in dem sie die OnRender Methode überschreiben. Wie dies auch bei OnPaint in WinForms der Fall ist.

    Doch beim Grid wird davon nicht Gebrauch gemacht um die Linien zu zeichnen! Stattdessen wird zu den logischen UI-Elementen in dem Panel ein zusätzliches visuelles Element der „GridLinesRenderer“ hinzugefügt. Dies geschieht nicht per ControlTemplate. (Templates ändern ebenfalls das Aussehen also den VisualTree), sonder programmatisch durch den Aufruf von AddVisualChild(visual) in der Basisklasse.

    Der GridLinesRenderer ist von DrawingVisual abgeleitet. UIElement und DrawingVisual haben also den Selben Vorfahr „Visual“. DrawingVisuals sind jedoch wesentlichen performanter als UIElements, da sie direkt auf den „Bildschrim“ (WPF-Subsystem) zeichnen.

    Der VisualTree im XamlPad zeigt, dass neben dem logischen Child – einem Button - noch ein visuelles Element - der GridLinesRenderer  - in der Hierarchie zu finden ist.

     

    Möglichkeit 1: Einen eigenen GridLinesRenderer schreiben

    Meine erste Idee war es einen eigenen GridLinesRenderer zu schreiben. Ganz nach dem Vorbild des in dem Grid zu findenden Renderer.

    Das Problem ist, dass es nicht möglich ist den Renderer in den VisualTree des Grid einzufügen. Die Methode die dieses möglich machen würde – AddVisualChild – ist nämlich protected.

    Ein eigenes Grid zu erstellen, nur um die GridLinien zeichnen zu können war mir dann aber zu aufwändig.

    Es muss einen anderen Weg geben.

    Möglichkeit 2: Einen GridLinesAdorner schreiben

    Wenn es keine Möglichkeit gibt ein UIElement von Innen zu verändern ohne ein eigenes Control abzuleiten, so muss man es eben von Außen probieren. Das machen sog. Adorner.

    Adorner „verzieren“ ein UIElement. Wie, das bestimmt der Adorner. Wichtig ist, dass ein Adorner immer über einem UIElement gezeichnet wird. D.h. der Adorner verdeckt darunter liegende Zeichnungen.

    Public Class GridLinesAdorner

        Inherits Adorner

     

        Private Grid As System.Windows.Controls.Grid

     

        'Übergabe des zu verzierenden Elements (hier Grid)

        Sub New(ByVal grid As System.Windows.Controls.Grid)

            MyBase.New(grid)

            Me.Grid = grid

        End Sub

     

        Private _pen As Pen

     

        'Stift um die Linien zeichnen zu können

        Public Property Pen() As Pen

            Get

                Return _pen

            End Get

            Set(ByVal value As Pen)

                _pen = value

            End Set

        End Property

     

     

        'Zeichnen der Linien

        Protected Overrides Sub OnRender(ByVal dc As System.Windows.Media.DrawingContext)

            If Pen Is Nothing Then Exit Sub

     

            If Grid.ColumnDefinitions.Count > 0 Then

                Dim x As Double

                For i As Integer = 1 To Grid.ColumnDefinitions.Count - 1

                    x = Grid.ColumnDefinitions(i).Offset

                    dc.DrawLine(Pen, New Point(x, 0), New Point(x, Grid.ActualHeight))

                Next

            End If

     

            If grid.RowDefinitions.Count > 0 Then

                Dim y As Double

                For i As Integer = 1 To Grid.RowDefinitions.Count - 1

                    y = Grid.RowDefinitions(i).Offset

                    dc.DrawLine(Pen, New Point(0, y), New Point(Grid.ActualWidth, y))

                Next

            End If

     

        End Sub

     

    End Class

     

    Die Methode OnRender führt nun das Zeichnen der Gridlinien durch. Über die Row- und ColumnDefinitions des Grid, kann der Offset der einzelnen Spalten vom Grid abgerufen werden. Diese dienen uns als Koordination um an diesen Stellen die entsprechenden Linien zu zeichnen.

    Anwenden des Adorners

    Um den Adorner zum Einsatz zu bringen, müssen wir nun noch die Code-Behind Datei anpassen. Leider ist es nicht möglich den Adorner in XAML direkt anzuwenden. (Die Klasse AdornerDecorator ist nur dafür da einen Layer für ein zu verzierendes Element bereitzustellen, worauf ein Adorner angewendet werden kann; aber nicht für den Adorner selbst.)

    Class Window1

     

        Private Sub Window1_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded

            'Layer für das Element holen in dem der Adorner gezeichnet wird

            Dim layer As AdornerLayer = AdornerLayer.GetAdornerLayer(Me.Grid)

            'Adorner mit Stift erstellen

            Dim adorner As New GridLinesAdorner(Grid)

            adorner.Pen = New Pen(Brushes.Black, 2)

            'Adorner dem Layer hinzufügen

            layer.Add(adorner)

        End Sub

     

    End Class

     

    Das Ergebnis

     

    Wer noch einen Rahmen um das Grid herum haben möchte, der brauch nur noch das Grid in ein Border zu packen.

    Achtung: Wie man sieht wird der Adorner über das Grid gezeichnet. Daher sind die Ränder der im Grid befindlichen Buttons nicht ganz zu sehen.

    Hier muss dann noch ein entsprechendes Margin auf die Buttons angewendet werden um den richtigen Abstand zu den Gridinnenseiten zu ermöglichen.

    • Beitragspunkte: 20
    • IP-Adresse ist Registriert
  • 05-08-2008 0:55 Antwort zu

    • jpkleinau
    • Top 10 Mitwirkender
      Männlich
    • Registriert am 05-07-2008
    • Frankfurt am Main
    • Beiträge 35
    • Punkte 505

    Re: Eigene Linien in Grid Panel zeichnen

    Hi Benjamin,

    finde ich gut, wenn du hier die Tutorials aus deinem Blog unterbringst. Aber leider sind die Bilder nicht sichtbar und ein paar Tippfehler hättest du auch killen können. Persönlich wäre mir ein Teaser und ein Link auf deinen Blog lieber gewesen, aber das mag Norbert, der hier die Community aufbaut, anders sehen.

    Die Adorner sind eine nette Möglichkeit, aber problematisch wird das Ganze doch, wenn ein Element mit Grid.ColumnSpan spielt. Hat schon Gründe, warum das nur für die Entwickler gedacht ist ;-)

    Liebe Grüße,

    Jens Peter

    • Beitragspunkte: 20
    • IP-Adresse ist Registriert
  • 05-08-2008 9:46 Antwort zu

    • Benjamin Gopp
    • Top 50 Mitwirkender
      Männlich
    • Registriert am 04-21-2008
    • Lohmar - Germany
    • Beiträge 4
    • Punkte 80

    AW: Re: Eigene Linien in Grid Panel zeichnen

    Hi Jens Peter,

    danke für die Hinweise. Ich werde noch mal über den Text gehen und die Rechtschreibfehler korrigieren. (Über meine Artikel liest sonst meine Frau immer drüber)

    Was das Doppelposting betrifft ist es immer eine Frage wo ich nach einem bestimmten Thema suche. Googelt jemand nach "Eigene Linien in Grid zeichnen", findet er mein Blog. Es gibt aber auch viele, die sich nur durch Foren hangeln, dann steht ein Hinweis in der Community.

    Übrigens versuche ich hier wirklich NEUE Dinge zu posten. Das mit den eigenen GridLines findest du in keinem Buch. Da steht immer nur "Das geht nicht". Geht aber doch!

    Dass die Bilder nicht angezeigt werden ist komisch. Vielleicht liegt es aber auch daran, dass man keine Bilder hier hochladen kann. So musste ich die Bilder von meinem Blog verlinken.

    An ColumnSpans habe ich nicht gedacht. Ich denke da fällt mir noch was ein.

    Gruß

    Benjamin

    • Beitragspunkte: 20
    • IP-Adresse ist Registriert
  • 05-08-2008 10:28 Antwort zu

    • jpkleinau
    • Top 10 Mitwirkender
      Männlich
    • Registriert am 05-07-2008
    • Frankfurt am Main
    • Beiträge 35
    • Punkte 505

    Re: AW: Re: Eigene Linien in Grid Panel zeichnen

    Benjamin Gopp:
    An ColumnSpans habe ich nicht gedacht. Ich denke da fällt mir noch was ein.

    Da habe ich gar keinen Zweifel Yes

    • Beitragspunkte: 5
    • IP-Adresse ist Registriert
Seite 1 von 1 (4 Treffer)
Powered by Community Server (Commercial Edition)    Hosting powered by 69° media solutions