locked
Umblättern RRS feed

  • Frage

  • Hallo,
    ich habe nochmal eine Frage zu einer animation und zwar das Umblättern einer Seite, denn ich will ein Buch simulieren. Meine Frage ist jetzt, wie das geht, besonders das mit Vor- und Rückseite.
    Ich wäre über eine kleine Anleitung sehr dankbar
    Clionel
    Samstag, 24. Oktober 2009 10:28

Antworten

  • Hallo Clionel,

    schau dir mal folgendes Projekt auf Codeplex an:

    http://wpfbookcontrol.codeplex.com/

    Schöne Grüße
    Oliver
    Samstag, 24. Oktober 2009 14:05
  • Hallo clionel,

    Lies bitte durch auch den folgenden Artikel. Vielleicht kann er Dir weiter helfen.

    http://msdn.microsoft.com/en-us/magazine/cc507644.aspx

    Grüße,

    Robert

    Donnerstag, 29. Oktober 2009 09:57
  • Hi Clionel,

     

    da ich mich am Wochenende gerade selbst mit dem Silverlight Book Control von Mitsu befaßt habe, kann ich Dir ein Sourcecode Beispiel in VB.NET geben. Die Sample Application von Mitsu ist in C#, ich programmiere in VB.NET. Deswegen mag das folgende Beispiel in VB.NET Code auch eine Hilfe für andere VB.NET Programmierer sein, wenn Sie keine Lust haben, die Beispielanwendung von Mitsu aus C# in VB.NET zu übersetzen.

     

    Ein Hinweis vorab: Ich programmiere derzeit Silverlight 2 in VS 2008, .NET 3.5 SP1.

     

    Als erstes brauchst Du einen Verweis auf die Datei SLMitsuControls.dll. Dann in der Page.xaml einen Verweis auf den Namespace:

     xmlns:local="clr-namespace:SLMitsuControls;assembly=SLMitsuControls"


    und in der Page.xaml.vb eine Imports-Anweisung:

    Imports SLMitsuControls

     

    Dann wird direkt im Grid Layoutroot ein UCBook Control eingefügt:


      <local:UCBook x:Name="book"
                    Margin="20"
                    Height="760"
                    Width="1200"/>
    


    Das UCBook Control hat wie Du siehst feste Größenangaben und nur eine Margin. Für die Page sind Width und Height im XAML auf Auto gesetzt.

    Rebuild your solution und dann ab in den Code behind für die Einrichtung der Seiten des UCBook, dem ich den Namen "book" gegeben habe.

    In der Code Behind Datei muss die Schnittstelle IDataProvider von Mitsu's BookControl einbezogen werden. Das erfolgt über die folgende Anweisung:

    Implements IDataProvider

     

     


    die bekanntlich direkt unter die Anweisung:

    Inherits UserControl


    eingefügt werden muss. Dabei ist es nach meiner Erfahrung wichtig, dass die Anweisung Implements IDataProvider nicht einfach per Copy Paste eingefügt, sondern selbst eingetippt und mit Return ein Zeilenwechsel eingefügt wird, weil dann automatisch die entsprechenden (leeren) Routinen zur Verarbeitung der Schnittstelle mit den Signaturen eingefügt werden:

      Public Function GetCount() As Integer Implements SLMitsuControls.IDataProvider.GetCount
    
      End Function
    
      Public Function GetItem(ByVal index As Integer) As Object Implements SLMitsuControls.IDataProvider.GetItem
    
      End Function


    Der Code dieser Routinen muss dann wie folgt ergänzt werden:

    Public Function GetCount() As Integer Implements SLMitsuControls.IDataProvider.GetCount
        Return pages.Count
      End Function
    
      Public Function GetItem(ByVal index As Integer) As Object Implements SLMitsuControls.IDataProvider.GetItem
        Return pages(index)
      End Function


    Teilweise muckte VS herum, wenn ich die Routinen, z.B. aus einem anderen Projekt, einfach per Copy/Paste übernommen habe. Deswegen meine hierzu empfohlene obige Vorgehensweise.

    Für die in den beiden Routinen verarbeiteten "pages" brauchst Du noch eine generische Private List (Of IrgendeinControl). Sinnvollerweise nimmt man eine List (Of Grid), um einen Container bereitzustellen, der dann weitere UIElemente aufnehmen kann, die später auf den einzelnen pages jeweils enthalten sein sollen:

    Private pages As List(Of Grid)


    Dann fehlt noch eine Routine für das LoadedEvent des UCBook, in diesem Beispiel also book_Loaded(...):

      Private Sub book_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles book.Loaded
    
        ' Code hinzufügen, der die Pages gestaltet.
    
      End Sub
    


    In dieser Routine - oder ausgelagert in dienende Functions - baut man dann die Gestaltung der einzelnen Pages ein. In diesem Beispiel habe ich als Container einer Buchseite jeweils ein Grid gewählt, indem ich die generische Liste pages als List (OfGrid) definiert habe. Du kannst aber die generische Liste z.B. auch aus Stackpanels oder  Canvas bilden. Denkbar ist auch, dass Du ein einzelnen UIElement nimmst, z.B. einen Button oder ein Image. Dann kannst Du aber natürlich keine Child-Elemente einfügen.

    Jedes Grid eines der pages bildet also im Beispiel das oberste UIElement einer jeweiligen Buchseite. In jedes Grid können die einzelnen Steuerelemente als Child-Elemente eingebaut werden. Das kann z.B. so aussehen:

      Private Sub book_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles book.Loaded
    
        ' Code hinzufügen, der die Pages gestaltet.
    
        pages = New List(Of Grid)
    
        For i As Integer = 1 To 4
    
          pages.Add(BuildPage(i))
    
        Next
    
        book.SetData(Me)
    
      End Sub
    
      Private Function BuildPage(ByVal pagina As Integer) As Grid
    
        Dim result As New Grid
    
        Dim bd As New Border
    
        With bd
          .BorderBrush = New SolidColorBrush(Colors.Gray)
          .BorderThickness = New Thickness(2)
          .CornerRadius = New CornerRadius(5)
          .Background = New SolidColorBrush(Colors.Black)
          .Margin = New Thickness(16)
          .VerticalAlignment = Windows.VerticalAlignment.Top
          .Height = 500
        End With
    
        Dim tb As New TextBlock With {.Text = " Dies ist Seite " + pagina.ToString + ".", _
                                       .Height = 30, _
                                       .FontSize = 26, _
                                       .Foreground = New SolidColorBrush(Colors.Brown)}
    
        bd.Child = tb
    
        With result
          .Height = 760
          .Background = New SolidColorBrush(Colors.Brown)
          .HorizontalAlignment = Windows.HorizontalAlignment.Stretch
          .VerticalAlignment = Windows.VerticalAlignment.Stretch
          .Children.Add(bd)
        End With
    
        Return result
    
      End Function


    Rebuild your solution, F5 und voila ... das Buch ist gebunden.

    Damit die Seiten auch beim Click des Users auf eine Seite reagieren, müssen noch zwei Routinen her:

      Private Sub NächsteSeite(ByVal sender As Object, ByVal e As RoutedEventArgs)
    
        book.AnimateToNextPage(500)
    
      End Sub
    
      Private Sub VorherigeSeite(ByVal sender As Object, ByVal e As RoutedEventArgs)
    
        book.AnimateToPreviousPage(700)
    
      End Sub


    auf die dann in der Routine book_Loaded noch ein Zugriff per AddHandler eingebaut werden muss. Die fertige book_Loaded sieht dann so aus:

      Private Sub book_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles book.Loaded
    
        ' Code hinzufügen, der die Pages gestaltet.
    
        pages = New List(Of Grid)
    
        For i As Integer = 1 To 4
    
          pages.Add(BuildPage(i))
    
        Next
    
        ' Handler für das Blättern per Click auf eine Buchseite einfügen:
        Dim c As Integer = 0
        For Each b As Grid In pages
          If ((c Mod 2) = 0) Then
            AddHandler b.MouseLeftButtonUp, AddressOf NächsteSeite
          Else
            AddHandler b.MouseLeftButtonUp, AddressOf VorherigeSeite
          End If
          c = (c + 1)
        Next
    
        book.SetData(Me)
    
      End Sub


    Das war's.

    Wenn Du jetzt noch auf den Wechsel von Seiten reagieren willst, dann geht das über die UCBook Methode OnPageTurned, in der Du dann die Parameter leftPageIndex und/oder rightPageIndex auswerten kannst, um festzustellen, von welcher Seite auf welche Seite gewechselt wurde. Dabei hat die erste in der UI sichtbare Seite den leftPageIndex -1, die zweite in der UI sichtbare Seite aber den leftPageIndex 2.

    Wenn Du mehr über die Mathematik eines BookControls und die Umsetzung der Algorithmen in Code erfahren willst, dann bietet der folgende Link einen auch visuell super umgesetzten instruktiven Zugang. Unter dem Link kann man auch den Sourcecode eines Silverlight 3 Beispiels herunterladen:

    http://www.cynergysystems.com/blogs/page/rickbarraza?entry=the_secret_behind_the_page

    Ich hoffe, das war hilfreich. Wenn Du noch Fragen hast, dann poste hier.


    Beste Grüße,
    M. (LawBot)



    Nachtrag:

    Um möglichst flexibel bei der Gestaltung der einzelnen Buchseiten zu bleiben, empfiehlt es sich, die pages As List(Of UIElement) zu definieren. Dadurch kann man dann jedes Steuerelement das von UIElement erbt, als oberstes Element einer page zuordnen. Man muss dann also nicht mehr die UIElemente einer jeden Seite unbedingt in ein Grid einbinden (auch wenn das meistens ausreicht), sondern kann als oberstes UIElement z.B. auf Seite 1 ein Image, auf Seite 2 ein Grid, auf Seite 3 einen Button, usw. unterbringen.

    Beste Grüße,
    M.
    Donnerstag, 19. November 2009 23:03

Alle Antworten

  • Hallo Clionel,

    schau dir mal folgendes Projekt auf Codeplex an:

    http://wpfbookcontrol.codeplex.com/

    Schöne Grüße
    Oliver
    Samstag, 24. Oktober 2009 14:05
  • Hallo und danke,
    ich werde mir das morgen noch mal genauer anschauen und gebe dir dann Bescheid, ob es für mich passt.
    Schönen Tag noch
    Clionel
    Samstag, 24. Oktober 2009 15:43
  • Hallo,
    kann mir vielleicht jemand eine kleine Einführung in das oben genannte Projekt geben? Das würde mir sehr helfen
    Danke im Vorraus
    Clionel
    Samstag, 24. Oktober 2009 18:09
  • Hallo clionel,

    Lies bitte durch auch den folgenden Artikel. Vielleicht kann er Dir weiter helfen.

    http://msdn.microsoft.com/en-us/magazine/cc507644.aspx

    Grüße,

    Robert

    Donnerstag, 29. Oktober 2009 09:57
  • Hallo clionel,

    Haben Dir die Antworten geholfen?

    Grüße,
    Robert

    Dienstag, 3. November 2009 12:15
  • Hallo clionel,

    Ich gehe davon aus, dass die Antworten Dir weitergeholfen haben.
    Solltest Du noch "Rückfragen" dazu haben, so gib uns bitte Bescheid.

    Grüße,
    Robert

    Freitag, 6. November 2009 15:32
  • Hi Clionel,

     

    da ich mich am Wochenende gerade selbst mit dem Silverlight Book Control von Mitsu befaßt habe, kann ich Dir ein Sourcecode Beispiel in VB.NET geben. Die Sample Application von Mitsu ist in C#, ich programmiere in VB.NET. Deswegen mag das folgende Beispiel in VB.NET Code auch eine Hilfe für andere VB.NET Programmierer sein, wenn Sie keine Lust haben, die Beispielanwendung von Mitsu aus C# in VB.NET zu übersetzen.

     

    Ein Hinweis vorab: Ich programmiere derzeit Silverlight 2 in VS 2008, .NET 3.5 SP1.

     

    Als erstes brauchst Du einen Verweis auf die Datei SLMitsuControls.dll. Dann in der Page.xaml einen Verweis auf den Namespace:

     xmlns:local="clr-namespace:SLMitsuControls;assembly=SLMitsuControls"


    und in der Page.xaml.vb eine Imports-Anweisung:

    Imports SLMitsuControls

     

    Dann wird direkt im Grid Layoutroot ein UCBook Control eingefügt:


      <local:UCBook x:Name="book"
                    Margin="20"
                    Height="760"
                    Width="1200"/>
    


    Das UCBook Control hat wie Du siehst feste Größenangaben und nur eine Margin. Für die Page sind Width und Height im XAML auf Auto gesetzt.

    Rebuild your solution und dann ab in den Code behind für die Einrichtung der Seiten des UCBook, dem ich den Namen "book" gegeben habe.

    In der Code Behind Datei muss die Schnittstelle IDataProvider von Mitsu's BookControl einbezogen werden. Das erfolgt über die folgende Anweisung:

    Implements IDataProvider

     

     


    die bekanntlich direkt unter die Anweisung:

    Inherits UserControl


    eingefügt werden muss. Dabei ist es nach meiner Erfahrung wichtig, dass die Anweisung Implements IDataProvider nicht einfach per Copy Paste eingefügt, sondern selbst eingetippt und mit Return ein Zeilenwechsel eingefügt wird, weil dann automatisch die entsprechenden (leeren) Routinen zur Verarbeitung der Schnittstelle mit den Signaturen eingefügt werden:

      Public Function GetCount() As Integer Implements SLMitsuControls.IDataProvider.GetCount
    
      End Function
    
      Public Function GetItem(ByVal index As Integer) As Object Implements SLMitsuControls.IDataProvider.GetItem
    
      End Function


    Der Code dieser Routinen muss dann wie folgt ergänzt werden:

    Public Function GetCount() As Integer Implements SLMitsuControls.IDataProvider.GetCount
        Return pages.Count
      End Function
    
      Public Function GetItem(ByVal index As Integer) As Object Implements SLMitsuControls.IDataProvider.GetItem
        Return pages(index)
      End Function


    Teilweise muckte VS herum, wenn ich die Routinen, z.B. aus einem anderen Projekt, einfach per Copy/Paste übernommen habe. Deswegen meine hierzu empfohlene obige Vorgehensweise.

    Für die in den beiden Routinen verarbeiteten "pages" brauchst Du noch eine generische Private List (Of IrgendeinControl). Sinnvollerweise nimmt man eine List (Of Grid), um einen Container bereitzustellen, der dann weitere UIElemente aufnehmen kann, die später auf den einzelnen pages jeweils enthalten sein sollen:

    Private pages As List(Of Grid)


    Dann fehlt noch eine Routine für das LoadedEvent des UCBook, in diesem Beispiel also book_Loaded(...):

      Private Sub book_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles book.Loaded
    
        ' Code hinzufügen, der die Pages gestaltet.
    
      End Sub
    


    In dieser Routine - oder ausgelagert in dienende Functions - baut man dann die Gestaltung der einzelnen Pages ein. In diesem Beispiel habe ich als Container einer Buchseite jeweils ein Grid gewählt, indem ich die generische Liste pages als List (OfGrid) definiert habe. Du kannst aber die generische Liste z.B. auch aus Stackpanels oder  Canvas bilden. Denkbar ist auch, dass Du ein einzelnen UIElement nimmst, z.B. einen Button oder ein Image. Dann kannst Du aber natürlich keine Child-Elemente einfügen.

    Jedes Grid eines der pages bildet also im Beispiel das oberste UIElement einer jeweiligen Buchseite. In jedes Grid können die einzelnen Steuerelemente als Child-Elemente eingebaut werden. Das kann z.B. so aussehen:

      Private Sub book_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles book.Loaded
    
        ' Code hinzufügen, der die Pages gestaltet.
    
        pages = New List(Of Grid)
    
        For i As Integer = 1 To 4
    
          pages.Add(BuildPage(i))
    
        Next
    
        book.SetData(Me)
    
      End Sub
    
      Private Function BuildPage(ByVal pagina As Integer) As Grid
    
        Dim result As New Grid
    
        Dim bd As New Border
    
        With bd
          .BorderBrush = New SolidColorBrush(Colors.Gray)
          .BorderThickness = New Thickness(2)
          .CornerRadius = New CornerRadius(5)
          .Background = New SolidColorBrush(Colors.Black)
          .Margin = New Thickness(16)
          .VerticalAlignment = Windows.VerticalAlignment.Top
          .Height = 500
        End With
    
        Dim tb As New TextBlock With {.Text = " Dies ist Seite " + pagina.ToString + ".", _
                                       .Height = 30, _
                                       .FontSize = 26, _
                                       .Foreground = New SolidColorBrush(Colors.Brown)}
    
        bd.Child = tb
    
        With result
          .Height = 760
          .Background = New SolidColorBrush(Colors.Brown)
          .HorizontalAlignment = Windows.HorizontalAlignment.Stretch
          .VerticalAlignment = Windows.VerticalAlignment.Stretch
          .Children.Add(bd)
        End With
    
        Return result
    
      End Function


    Rebuild your solution, F5 und voila ... das Buch ist gebunden.

    Damit die Seiten auch beim Click des Users auf eine Seite reagieren, müssen noch zwei Routinen her:

      Private Sub NächsteSeite(ByVal sender As Object, ByVal e As RoutedEventArgs)
    
        book.AnimateToNextPage(500)
    
      End Sub
    
      Private Sub VorherigeSeite(ByVal sender As Object, ByVal e As RoutedEventArgs)
    
        book.AnimateToPreviousPage(700)
    
      End Sub


    auf die dann in der Routine book_Loaded noch ein Zugriff per AddHandler eingebaut werden muss. Die fertige book_Loaded sieht dann so aus:

      Private Sub book_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles book.Loaded
    
        ' Code hinzufügen, der die Pages gestaltet.
    
        pages = New List(Of Grid)
    
        For i As Integer = 1 To 4
    
          pages.Add(BuildPage(i))
    
        Next
    
        ' Handler für das Blättern per Click auf eine Buchseite einfügen:
        Dim c As Integer = 0
        For Each b As Grid In pages
          If ((c Mod 2) = 0) Then
            AddHandler b.MouseLeftButtonUp, AddressOf NächsteSeite
          Else
            AddHandler b.MouseLeftButtonUp, AddressOf VorherigeSeite
          End If
          c = (c + 1)
        Next
    
        book.SetData(Me)
    
      End Sub


    Das war's.

    Wenn Du jetzt noch auf den Wechsel von Seiten reagieren willst, dann geht das über die UCBook Methode OnPageTurned, in der Du dann die Parameter leftPageIndex und/oder rightPageIndex auswerten kannst, um festzustellen, von welcher Seite auf welche Seite gewechselt wurde. Dabei hat die erste in der UI sichtbare Seite den leftPageIndex -1, die zweite in der UI sichtbare Seite aber den leftPageIndex 2.

    Wenn Du mehr über die Mathematik eines BookControls und die Umsetzung der Algorithmen in Code erfahren willst, dann bietet der folgende Link einen auch visuell super umgesetzten instruktiven Zugang. Unter dem Link kann man auch den Sourcecode eines Silverlight 3 Beispiels herunterladen:

    http://www.cynergysystems.com/blogs/page/rickbarraza?entry=the_secret_behind_the_page

    Ich hoffe, das war hilfreich. Wenn Du noch Fragen hast, dann poste hier.


    Beste Grüße,
    M. (LawBot)



    Nachtrag:

    Um möglichst flexibel bei der Gestaltung der einzelnen Buchseiten zu bleiben, empfiehlt es sich, die pages As List(Of UIElement) zu definieren. Dadurch kann man dann jedes Steuerelement das von UIElement erbt, als oberstes Element einer page zuordnen. Man muss dann also nicht mehr die UIElemente einer jeden Seite unbedingt in ein Grid einbinden (auch wenn das meistens ausreicht), sondern kann als oberstes UIElement z.B. auf Seite 1 ein Image, auf Seite 2 ein Grid, auf Seite 3 einen Button, usw. unterbringen.

    Beste Grüße,
    M.
    Donnerstag, 19. November 2009 23:03