Metro Apps Tutorial

    • Modern UI

    Es gibt 9 Antworten in diesem Thema. Der letzte Beitrag () ist von Leonalter.

      Metro Apps Tutorial

      Da jetzt mit Windows 8 die Metro Apps für VB-Entwickler immer wichtiger werden, wollte ich einmal ein paar Metro spezifische Erklärungen geben.
      Voraussetzung für dieses Tutorial ist Windows 8 und Visual Studio 2012.

      Hintergrundwissen:
      - Laut Microsoft müssen Metro Apps "fast and fluid" laufen, somit also größtenteils asynchron entwickelt werden. Denn asynchrone Vorgänge "frieren" die App nicht ein.
      - Die Apps müssen im Vollbild und an den Rand angedockt gleichermaßen laufen (wenn das bei der App Sinn macht)
      - Die meistgenutzte Bildschirmgröße wird wohl 1366x768 werden, darunter wird es nichts geben.

      XAML & Grundlagen:
      Grundlegend kann man sich auch kurz bei WPF darüber einlesen, falls man noch gar nichts gemacht hat
      WPF XAML Grundlagen, geeignet wenn man noch gar keine Erfahrung mit XAML hat (dafür danke an Andi2572)

      Projekt erstellen
      Spoiler anzeigen

      1). Microsoft Visual Studio 2012 RC runterladen und installieren
      2). Neues Projekt
      3). Links Visual Basic und Windows Metro Style auswählen
      4). Für den Anfang nehmen wir die Vorlage Blank App (XAML)
      5). Name eingeben und OK
      6). Am Anfang landet ihr wahrscheinlich in der Datei "App.xaml", die schließt ihr einfach und klickt doppelt auf "MainPage.xaml", dann seid ihr im gewohnten Designer. Um ins Codefenster zu gelangen einfach Rechtsklick -> View Code


      ViewBox
      Spoiler anzeigen

      Die ViewBox skaliert ihren Inhalt immer auf ihre eigene Größe.
      Also muss aus

      Quellcode

      1. <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
      2. </Grid>

      das hier werden:

      Quellcode

      1. <Viewbox Stretch="UniformToFill">
      2. <Grid Height="768" Width="1366" Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
      3. </Grid>
      4. </Viewbox>

      Der Inhalt des Grids wird so auf jeder Bildschirmgröße immer in der Größe 1366x768 auftauchen. Am Grid wurde außerdem noch eine Höhen- und Breitenangabe gemacht.


      VisualState(An Seite angedockt)
      Spoiler anzeigen

      Mithilfe dieser Abfrage kann man für die Logik wichtige Sachen machen, sie fragt einfach den VisualState ab:

      VB.NET-Quellcode

      1. If ApplicationView.Value = ApplicationViewState.Snapped Then
      2. 'Hier was machen wenn der ApplicationView Snapped ist
      3. End If

      Jetzt kommt noch die elegante Lösung mit den VisualstateManager. Diese wird allgemein für das Layout genutzt, ist dafür auch sehr praktisch, da das ganze sehr schnell und schön von statten geht:
      1). Diesen XAML Code reinkopieren in den größten Container (meistens das standartmäßig erstellte Grid):

      XML-Quellcode

      1. <VisualStateManager.VisualStateGroups>
      2. <VisualStateGroup x:Name="ApplicationViewStates">
      3. <VisualState x:Name="FullScreenLandscape"/>
      4. <VisualState x:Name="Filled"/>
      5. <VisualState x:Name="FullScreenPortrait"/>
      6. <VisualState x:Name="Snapped"/>
      7. </VisualStateGroup>
      8. </VisualStateManager.VisualStateGroups>

      2). In der Codeansicht kommt dieses Event einfach unter "Inherits Page" (bei der Blank Page):

      VB.NET-Quellcode

      1. Private Sub MainPage_SizeChanged(sender As Object, e As SizeChangedEventArgs) Handles Me.SizeChanged
      2. VisualStateManager.GoToState(Me, ApplicationView.Value.ToString, True)
      3. End Sub

      3). Jetzt kann man das Layout bearbeiten für die verschiedenen VisualStates. Da wäre einmal FullScreenLandscape, das bedeutet Breitbild und ist standartmäßig aktiviert, dann gibt es noch "Filled", das bedeutet, dass die eigene App groß ist und eine fremde App angedockt ist. "FullScreenPortrait" bedeutet hochkant, ist bei Tablets meistens auch sehr wichtig. Und bei vielen Apps ist "Snapped" wohl das wichtigste, das bedeutet, dass die App an die Seite angedockt ist.
      Jetzt geht man auf das Gerätefenster (Entwurf -> Gerätefenster), wählt in der Box neben "Visual state" den gewünschten Visualstate aus, für den Änderungen gemacht werden sollen und klickt auf "Enable State recording". Dann einfach an den Controls wüst herumreißen und schon hat man die richtigen Änderungen für den richtigen Visualstate.


      Seiten wechseln
      Spoiler anzeigen
      Dim rootFrame As New Frame
      rootFrame.Navigate(GetType(NeueSeite))

      Window.Current.Content = rootFrame
      Window.Current.Activate()


      Übersetzungen aus dem Desktop/ bekanntes:

      MsgBox:
      Spoiler anzeigen

      Damit man das ganze überhaupt machen kann, muss die Methode noch als Asynchron erkannt werden, aus

      VB.NET-Quellcode

      1. Private Sub

      wird

      VB.NET-Quellcode

      1. Private Async Sub

      Desktopcode:

      VB.NET-Quellcode

      1. MessageBox.Show("Ich bin ein Dialogfeld")

      Übersetzung:

      VB.NET-Quellcode

      1. Await New Windows.UI.Popups.MessageDialog("Ich bin ein Dialogfeld").ShowAsync()

      Sollte man das "Await" am Anfang weglassen, läuft die App während das Dialogfeld angezeigt wird weiter.


      Tastaturabfrage:
      Spoiler anzeigen

      Die Tastaturabfrage per "KeyDown" Event funktioniert bei Metro Apps in der Release Preview bisher nur bei Elementen, denen man den Focus geben kann. Zum Beispiel TextBoxen, Button usw.
      1). Das KeyDown Event eines beliebigen Elements nehmen, ein TextBlock "LblAnzeige" wird benötigt
      2). Das hier nehme ich mal als Beispiel, was man dann in dem Event machen kann:

      VB.NET-Quellcode

      1. LblAnzeige.Text = e.Key 'ASCII Code anzeigen
      2. LblAnzeige.Text = e.Key.ToString 'Die Taste anzeigen

      Oder auch:

      VB.NET-Quellcode

      1. If e.Key = Windows.System.VirtualKey.A Then 'A abfragen
      2. 'Etwas tun, wenn A gedrückt wurde.
      3. End If



      Mausposition im Mousemove Event abfragen
      Spoiler anzeigen

      1). Projekt erstellen -> Visual Basic -> Windows Metro Style -> Blank App (XAML) -> Name eingeben
      2). Doppelklick auf MainPage.xaml
      3). Dem Grid einen Namen geben:

      Quellcode

      1. <Grid x:Name="MainGrid"...>

      4). Ein TextBlock-Element auf die Form ziehen -> Noch einen Namen geben
      5). in den Code gehen (Rechtsklick auf "Mainpage.xaml" -> View Code)
      6). Das PointerMove Event erzeugen (Erst Oben Links die Box mit den Elementen auswählen und dann auf Mainpage_Events, dann oben rechts auf Pointermoved
      7). Jetzt tragen wir diesen Code in die gerade erstellte Methode ein:

      VB.NET-Quellcode

      1. TxtAnzeige.Text = e.GetCurrentPoint(relativeTo:=MainGrid).Position.ToString

      Das bringt jetzt den aktuellen Punkt des Mauszeigers im MainGrid auf den TextBlock TxtAnzeige
      Hier nochmal alle aktuellen Codes:

      Quellcode

      1. <Page
      2. x:Class="MauspositionImMouseMoveEvent.MainPage"
      3. IsTabStop="false"
      4. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      5. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      6. xmlns:local="using:MauspositionImMouseMoveEvent"
      7. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      8. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      9. mc:Ignorable="d">
      10. <Grid x:Name="MainGrid" Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
      11. <TextBlock x:Name="TxtAnzeige" HorizontalAlignment="Left" Margin="10,10,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Height="71" Width="171"/>
      12. </Grid>
      13. </Page>

      VB.NET-Quellcode

      1. Public NotInheritable Class MainPage
      2. Inherits Page
      3. Private Sub MainPage_PointerMoved(sender As Object, e As PointerRoutedEventArgs) Handles Me.PointerMoved
      4. TxtAnzeige.Text = e.GetCurrentPoint(relativeTo:=MainGrid).Position.ToString
      5. End Sub
      6. End Class



      Objekte Erstellen
      Spoiler anzeigen

      Ich erstelle jetzt mal als Beispiel eine Ellipse während der Laufzeit:
      XAML: (Ein Button hinzugefügt und dem Grid einen Namen geben)

      Quellcode

      1. <Grid x:Name="MainGrid" Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
      2. <Button Content="Button" HorizontalAlignment="Left" Margin="69,65,0,0" VerticalAlignment="Top" Click="Button_Click_1"/>
      3. </Grid>

      VB: (auf den Button Doppelklicken und der Code hier versteht sich ja eigentlich von selbst...

      VB.NET-Quellcode

      1. Public NotInheritable Class MainPage
      2. Inherits Page
      3. Dim GameEllipse As New Windows.UI.Xaml.Shapes.Ellipse
      4. Private Sub Button_Click_1(sender As Object, e As RoutedEventArgs)
      5. GameEllipse.Height = 100
      6. GameEllipse.Width = 100
      7. GameEllipse.Fill = New SolidColorBrush(Windows.UI.Color.FromArgb(255, 123, 152, 192))
      8. GameEllipse.Margin = New Thickness(0, 0, 0, 0)
      9. MainGrid.Children.Add(GameEllipse)
      10. End Sub
      11. End Class



      Timer
      Spoiler anzeigen

      Hier werde ich mal kurz darauf eingehen, wie man das gleiche Ergebnis erziehlt, wie bei dem Timer, den man immer auf die Form gezogen hat -> Doppelklick -> im Tick Ereignis war.
      1). Projekt erstellen "Beispieltimer" (Blank App)
      2). Im Designer ein Textblock (LblAnzeige) und zwei Buttons (BtnStart, BtnStop) hinzufügen, oder diesen xaml Code reinkopieren:

      Quellcode

      1. <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
      2. <Button x:Name="BtnStart" Content="Start" HorizontalAlignment="Left" Margin="41,26,0,0" VerticalAlignment="Top" Width="119" Click="BtnStart_Click_1" />
      3. <Button x:Name="BtnStop" Content="Stop" HorizontalAlignment="Left" Margin="165,26,0,0" VerticalAlignment="Top" Width="123" Click="BtnStop_Click_1"/>
      4. <TextBlock x:Name="LblAnzeige" FontSize="36" HorizontalAlignment="Left" Margin="41,80,0,0" TextWrapping="Wrap" Text="0" VerticalAlignment="Top" Width="247" Height="60"/>
      5. </Grid>

      3). Dadurch wurden jetzt auch automatisch zwei Events im Code erstellt, nämlich die beiden Klicks auf die Buttons. Ziel dieses Beispiels wird es sein, einfach eine Zahl bei jedem Tick im Timer +1 zu rechnen. Dafür deklarieren wir jetzt erstmal den Timer, direkt unter "Inherits Page":

      VB.NET-Quellcode

      1. Dim WithEvents MainTimer As New DispatcherTimer

      und holen uns das Event wie gewohnt oben aus den beiden Comboboxen (Tick). Als Zwischenstufe sollte der Code jetzt so aussehen:

      VB.NET-Quellcode

      1. Public NotInheritable Class MainPage
      2. Inherits Page
      3. Dim WithEvents MainTimer As New DispatcherTimer
      4. Private Sub BtnStart_Click_1(sender As Object, e As RoutedEventArgs)
      5. End Sub
      6. Private Sub BtnStop_Click_1(sender As Object, e As RoutedEventArgs)
      7. End Sub
      8. Private Sub MainTimer_Tick(sender As Object, e As Object) Handles MainTimer.Tick
      9. End Sub
      10. End Class

      Jetzt schreiben wir einfach in das Klickevent des Buttons "BtnStart" "MainTimer.Start" rein und in das des Buttons "BtnStop" "MainTimer.Stop". In das "Tick" Event nehmen wir einfach immer den Wert des Textblocks "LblAnzeige" +1:

      VB.NET-Quellcode

      1. Public NotInheritable Class MainPage
      2. Inherits Page
      3. Dim WithEvents MainTimer As New DispatcherTimer
      4. Private Sub BtnStart_Click_1(sender As Object, e As RoutedEventArgs)
      5. MainTimer.Start()
      6. End Sub
      7. Private Sub BtnStop_Click_1(sender As Object, e As RoutedEventArgs)
      8. MainTimer.Stop()
      9. End Sub
      10. Private Sub MainTimer_Tick(sender As Object, e As Object) Handles MainTimer.Tick
      11. LblAnzeige.Text = (Convert.ToInt32(LblAnzeige.Text) + 1).ToString
      12. End Sub
      13. End Class

      Dieser Beitrag wurde bereits 24 mal editiert, zuletzt von „Telcrome“ ()

      Dateien erstellen, bearbeiten, auslesen und löschen:
      Spoiler anzeigen

      Vorab:
      Dieser Unterpunkt beschreibt, wie man Dateien in der Dokumentenbibliothek nutzen kann. Sind also für den Nutzer sichtbar. Für Dinge, die der Nutzer nicht in seinen Dokumenten braucht, solltet ihr lieber die eigene Storage Umgebung nutzen. Sonst kommt die App sicher nicht in den Store rein.
      1). Blank App (XAML) erstellen und "Dateienverwaltung" nennen
      2). Da die Metroapps diese Funktion eigentlich gar nicht nutzen dürften, muss man erstmal das Nutzungsrecht erstellen. Dazu öffnet man die Datei "Package.appxmanifest" -> Capabilities.
      Jetzt ein Häckchen bei Documents Library Access machen.
      Der jetzt auftauchende Fehler wird wohl in der finalen Version behoben werden, aber jetzt müssen wir ihn noch behandeln. Er äußert sich durch das rote X, das neben Capabilities angezeigt wird. Es geht darum, dass man zwar auf die Dokumente zugreifen kann, jedoch keinen Dateityp speichern.
      Um ihn zu beheben gehen wir auf Rechtsklick "Package.appxmanifest" -> View Code.
      Da muss jetzt der Code hier unter </VisualElements> eingefügt werden:

      Quellcode

      1. <Extensions>
      2. <Extension Category="windows.fileTypeAssociation">
      3. <FileTypeAssociation Name="data">
      4. <EditFlags AlwaysUnsafe="true" />
      5. <SupportedFileTypes>
      6. <FileType>.txt</FileType>
      7. </SupportedFileTypes>
      8. </FileTypeAssociation>
      9. </Extension>
      10. </Extensions>

      Zur Überprüfung:

      XML-Quellcode

      1. <?xml version="1.0" encoding="utf-8[...]
      2. </VisualElements>
      3. <Extensions>
      4. <Extension Category="windows.fileTypeAssociation">
      5. <FileTypeAssociation Name="data">
      6. <EditFlags AlwaysUnsafe="true" />
      7. <SupportedFileTypes>
      8. <FileType>.txt</FileType>
      9. </SupportedFileTypes>
      10. </FileTypeAssociation>
      11. </Extension>
      12. </Extensions>
      13. </Application>
      14. </Applications>
      15. <Capabilities>
      16. <Capability Name="documentsLibrary" />
      17. <Capability Name="internetClient" />
      18. </Capabilities>
      19. </Package>

      Jetzt kann man den Dateityp ".txt" nutzen.
      3). MainPage.xaml öffnen
      4). Ich geh mal kurz das Deutschland - Italien Spiel schauen...
      5). Um die EM trauern
      6). Das standartmäßig erstellte Grid dann mit diesem hier ersetzen:

      Quellcode

      1. <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
      2. <TextBox x:Name="TxtEingabe" HorizontalAlignment="Left" Margin="10,10,0,0" TextWrapping="Wrap" Text="Dieser Text kommt in der Datei" VerticalAlignment="Top" Width="333"/>
      3. <TextBlock x:Name="LblAnzeige" FontSize="26" HorizontalAlignment="Left" Margin="10,207,0,0" TextWrapping="Wrap" Text="Anzeige" VerticalAlignment="Top" Width="333" Height="83"/>
      4. <Button x:Name="CmdErstellen" Content="Erstellen" HorizontalAlignment="Left" Margin="10,47,0,0" VerticalAlignment="Top" Height="75" Width="148" Click="CmdErstellen_Click_1" />
      5. <Button x:Name="CmdBearbeiten" Content="Bearbeiten" HorizontalAlignment="Left" Margin="195,47,0,0" VerticalAlignment="Top" Height="75" Width="148" Click="CmdBearbeiten_Click_1"/>
      6. <Button x:Name="CmdAuslesen" Content="Auslesen" HorizontalAlignment="Left" Margin="10,127,0,0" VerticalAlignment="Top" Height="75" Width="148" Click="CmdAuslesen_Click_1"/>
      7. <Button x:Name="CmdLoeschen" Content="Löschen" HorizontalAlignment="Left" Margin="195,127,0,0" VerticalAlignment="Top" Height="75" Width="148" Click="CmdLoeschen_Click_1"/>
      8. <TextBlock HorizontalAlignment="Left" Margin="10,295,0,0" TextWrapping="Wrap" Text="Also hier sind jetzt einfach nur die Vier Buttons, die Textbox in der der Text steht, der später in die Datei geschrieben wird und eine Anzeige, was gerade gemacht wird. Das ganze ist knapp an der Seite gehalten, damit die App an den Rand angedockt werden kann und man somit die Veränderung in den Dokumenten bewundern kann^^" VerticalAlignment="Top" Height="127" Width="333"/>
      9. </Grid>

      Die verschiedenen Methoden, die benötigt werden, dürften dann auch schon aufgetaucht sein.
      6.3). "Windows.Storage" importieren.
      6.5). Eine Datei deklarieren, direkt unter "Inherits Page":

      VB.NET-Quellcode

      1. Dim TutorialFile As StorageFile

      6.7). Damit wir später "Await" nutzen können, sollten wir jetzt alle Subs zu asynchronen Subs machen.
      7). In den Code gehen, der sollte jetzt so aussehen: (Natürlich eigentlich noch mit dem OnNavigatedTo-Ereignis, welches wir jedoch für dieses Tutorial nicht brauchen und ein paar Kommis)

      VB.NET-Quellcode

      1. Imports Windows.Storage
      2. Public NotInheritable Class MainPage
      3. Inherits Page
      4. Dim TutorialFile As StorageFile
      5. Private Async Sub CmdErstellen_Click_1(sender As Object, e As RoutedEventArgs)
      6. End Sub
      7. Private Async Function CmdBearbeiten_Click_1(sender As Object, e As RoutedEventArgs) As Task
      8. End Function
      9. Private Async Sub CmdAuslesen_Click_1(sender As Object, e As RoutedEventArgs)
      10. End Sub
      11. Private Async Sub CmdLoeschen_Click_1(sender As Object, e As RoutedEventArgs)
      12. End Sub
      13. End Class

      8). Jetzt gibt es relativ einfach Codes für die verschiedenen Aktionen.
      Um eine Datei zu erstellen:

      VB.NET-Quellcode

      1. TutorialFile = Await KnownFolders.DocumentsLibrary.CreateFileAsync("TutorialFile.txt", CreationCollisionOption.ReplaceExisting)

      Optional kann man zum testen jetzt noch etwas in den TextBlock "LblAnzeige" schreiben.

      VB.NET-Quellcode

      1. LblAnzeige.Text = "Die Datei " & TutorialFile.Name & " kann jetzt bearbeitet werden"

      Ihr könnt jetzt schon mal die App ausführen (F5) und dann an den Rand andocken. In den Hauptbildschirm holt ihr kurz den Desktop und öffnet im Explorer die "Dokumente". Wenn ihr jetzt in der App auf "Erstellen" drückt, sollte sich in den Dokumenten eine Datei namens "Tutorial.txt" befinden.

      Um jetzt die Datei zu bearbeiten:

      VB.NET-Quellcode

      1. Await FileIO.WriteTextAsync(TutorialFile, TxtEingabe.Text)

      Hier wird jetzt einfach der Inhalt des Storagefiles "TutorialFile" auf TxtEingabe.Text gesetzt.

      Um den Inhalt der Datei in einer MsgBox anzeigen zu lassen:
      Await New Windows.UI.Popups.MessageDialog(Await FileIO.ReadTextAsync(TutorialFile)).ShowAsync()

      Um die Datei zu löschen:

      VB.NET-Quellcode

      1. Await TutorialFile.DeleteAsync


      Jetzt sollte alles zusammen so aussehen:

      VB.NET-Quellcode

      1. Imports Windows.Storage
      2. Public NotInheritable Class MainPage
      3. Inherits Page
      4. Dim TutorialFile As StorageFile
      5. Private Async Sub CmdErstellen_Click_1(sender As Object, e As RoutedEventArgs)
      6. TutorialFile = Await KnownFolders.DocumentsLibrary.CreateFileAsync("TutorialFile.txt", CreationCollisionOption.ReplaceExisting)
      7. LblAnzeige.Text = "Die Datei " & TutorialFile.Name & " kann jetzt bearbeitet werden"
      8. End Sub
      9. Private Async Function CmdBearbeiten_Click_1(sender As Object, e As RoutedEventArgs) As Task
      10. Await FileIO.WriteTextAsync(TutorialFile, TxtEingabe.Text)
      11. End Function
      12. Private Async Sub CmdAuslesen_Click_1(sender As Object, e As RoutedEventArgs)
      13. Await New Windows.UI.Popups.MessageDialog(Await FileIO.ReadTextAsync(TutorialFile)).ShowAsync()
      14. End Sub
      15. Private Async Sub CmdLoeschen_Click_1(sender As Object, e As RoutedEventArgs)
      16. Await TutorialFile.DeleteAsync
      17. End Sub
      18. End Class


      Die Datei kann außerdem eingelesen werden, damit man im Programm wieder damit arbeiten kann, ohne sie vorher zu erstellen:

      VB.NET-Quellcode

      1. TutorialFile = Await KnownFolders.DocumentsLibrary.CreateFileAsync("TutorialFile.txt", CreationCollisionOption.OpenIfExists)


      Das letzte ist dann wohl das abfragen, ob eine Datei bereits eingelesen wurde:

      VB.NET-Quellcode

      1. If TutorialFile IsNot Nothing Then
      2. 'Anweisungen, wenn die Datei da ist.
      3. Else
      4. 'Anweisungen, wenn die Datei noch nicht eingelesen wurde.
      5. End If



      Metrofunktionen
      Für "Teilen" siehe meinen Post weiter unten
      Settings in der Charm Bar:
      Spoiler anzeigen

      Vorab:
      Die Settings in der Charm Bar sind einfach nur Buttons, von denen ihr ein Event kriegt. Von MS ist in den Appbestimmungen vorgeschrieben, dass alle Einstellungen für die App auch wirklich da zu finden sind. Dadurch soll sich der Nutzer in allen Apps zurechtfinden können.
      0.5). Projekt namens "Settings erstellen
      Die Settings aus dem Programm heraus öffnen:
      1). Ein Button in das Grid setzen, z.B. den hier:

      Quellcode

      1. <Button x:Name="CmdSettingsAnzeigen" Content="Settings anzeigen" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="201" Height="61" Click="CmdSettingsAnzeigen_Click_1"/>

      2). In das Click-Ereignis des Buttons diesen Code eintragen und ein Import:

      VB.NET-Quellcode

      1. Imports Windows.UI.Popups
      2. Imports Windows.UI.ApplicationSettings 'kommt über "Public NotInheritable Class"

      VB.NET-Quellcode

      1. SettingsPane.Show()

      Jetzt könnte man schon einmal testen und wird sehen, dass die Settings geöffnet sind, aber noch kein selbst hinzugefügtes Element drinsteht.
      3). Ein Element hinzufügen
      3.1). Einen neuen Button fürs hinzufügen:

      Quellcode

      1. <Button x:Name="CmdElementHinzufuegen" Content="Element hinzufügen" HorizontalAlignment="Left" Margin="10,71,0,0" VerticalAlignment="Top" Width="351" Height="61" Click="CmdElementHinzufuegen_Click_1"/>

      3.2). Um die Settings hinzuzufügen, nehme ich mal eine Methode, in die man dann einfach alle Settings reinschreibt, die hinzugefügt werden sollen:

      VB.NET-Quellcode

      1. Private Sub Die_Methode_Fuer_die_Settings(settingsPane As SettingsPane, eventArgs As SettingsPaneCommandsRequestedEventArgs)
      2. End Sub

      Nach diesem Schema werden dann, sollte diese Methode durchlaufen, die Settings hinzugefügt:

      VB.NET-Quellcode

      1. eventArgs.Request.ApplicationCommands.Add(New SettingsCommand("Tutorialsetting", "Tutorialsetting", New UICommandInvokedHandler(AddressOf Tutorialsetting_Click)))

      Ein recht komplizierter Einzeiler, bei dem man dann einfach die Strings "Tutorialsetting" durch den gewünschten Namen ersetzt.
      Jetzt wird man noch einen Fehler erhalten, weil dem Setting noch keine Methode zugeordnet ist, die aufgerufen wird, wenn man auf das Setting klickt. Also schreibt man für diese hier:

      VB.NET-Quellcode

      1. Private Async Sub Tutorialsetting_Click(command As IUICommand)
      2. Await New Windows.UI.Popups.MessageDialog("Das Tutorialsetting wurde erfolgreich hinzugefügt.").ShowAsync()
      3. End Sub

      Hier wird jetzt einfach eine Messagebox aufgerufen, siehe in diesem Tutorial den Punkt "MsgBox".
      3.3). Jetzt muss noch die Methode für das Hinzufügen der Settings irgendwo aufgerufen werden. Das macht natürlich eigentlich vor allem in dem Load Ereignis Sinn, aber hier wird das jetzt zur Veranschaulichung in einem Button gemacht:

      VB.NET-Quellcode

      1. Private Sub CmdElementHinzufuegen_Click_1(sender As Object, e As RoutedEventArgs)
      2. AddHandler SettingsPane.GetForCurrentView.CommandsRequested, AddressOf Die_Methode_Fuer_die_Settings
      3. End Sub

      3.4). Testen. Auf dem ersten Button sollte jetzt das Settingspane angezeigt werden, der zweite fügt ein Element hinzu, das Element selbst ruft ein Dialogfeld auf.
      Zur Übersicht einmal der gesamte Code:

      VB.NET-Quellcode

      1. Imports Windows.UI.ApplicationSettings
      2. Imports Windows.UI.Popups
      3. Public NotInheritable Class MainPage
      4. Inherits Page
      5. Private Sub CmdSettingsAnzeigen_Click_1(sender As Object, e As RoutedEventArgs)
      6. SettingsPane.Show()
      7. End Sub
      8. Private Sub CmdElementHinzufuegen_Click_1(sender As Object, e As RoutedEventArgs)
      9. AddHandler SettingsPane.GetForCurrentView.CommandsRequested, AddressOf Die_Methode_Fuer_die_Settings
      10. End Sub
      11. Private Sub Die_Methode_Fuer_die_Settings(settingsPane As SettingsPane, eventArgs As SettingsPaneCommandsRequestedEventArgs)
      12. eventArgs.Request.ApplicationCommands.Add(New SettingsCommand("Tutorialsetting", "Tutorialsetting", New UICommandInvokedHandler(AddressOf Tutorialsetting_Click)))
      13. End Sub
      14. Private Async Sub Tutorialsetting_Click(command As IUICommand)
      15. Await New Windows.UI.Popups.MessageDialog("Das Tutorialsetting wurde erfolgreich hinzugefügt.").ShowAsync()
      16. End Sub
      17. End Class



      Progressring:
      Spoiler anzeigen

      Ihr nehmt einen Progressring aus der Toolbox, zieht ihn auf die Form und setzt dann diesen Code an die Stelle, an der er erscheinen soll:

      VB.NET-Quellcode

      1. ProgressRing.IsActive = True

      Soll er wieder deaktiviert werden, wieder auf False setzen.


      Beispielanwendungen

      Hier werde ich noch eigene (sehr kleine, somit gut verständliche) Metroanwendungen posten (die ich selber zum üben nehme), würde mich natürlich auch über Beispielapps von anderen freuen.

      Empfohlene Videotutorials
      Umgang mit dem Webview, skaliert automatisch auf die jeweilige Bildschirmgröße:
      Hier klicken um zum Video zu gelangen.
      Metro Apps bei anderen zum laufen bringen:
      youtube.com/watch?v=q_9XUe4C9Hk&feature=plcp

      Aktuell fehlt noch:
      - XAML (Animationen, allgemeine Einführung)
      - Die Charm Bar(Charm Bar öffnen, Share Charm nutzen, Suche nutzen)
      - Emails senden
      - OpenfileDialog
      - Sowas wie GDI+, nur eben für Metro (oder Nennung einer Alternative)
      - TCP/IP Ersatz für Chat und Spiele

      Hier ist außerdem auch noch ein gutes Tutorial

      Weitere Fragen zu Metro Apps werde ich nach Möglichkeit beantworten

      Dieser Beitrag wurde bereits 12 mal editiert, zuletzt von „Telcrome“ ()

      hab ich unter XAML Grundlagen gestellt, danke!



      Teilen:
      Spoiler anzeigen

      Beim Teilen handelt es sich um die Funktion, die durch die Charm Bar erreicht wird. Das ganze ist recht einfach, somit auch gut in jede App zu integrieren.

      Der eigentlich Vorgang besteht aus zwei Parteien. Der Source App und der Target App.
      Ich werde jetzt hier auf die Programmierung einer Source App eingehen. Die Source App gibt z.B. einen Text (das werde ich gleich zeigen) oder einen anderen Dateityp frei und die Target App, die dann vom Nutzer ausgewählt wird, kann diese weitergeben.
      Ich zum Beispiel habe bei mir die Target Apps "Mail", "Kontakte" (für Facebook) und "MetroTweet" installiert.

      Fangen wir jetzt mal an. Die nun von uns programmierte App kann gleich den Text, den wir in eine TextBox eintragen, sharen.
      1). Projekt mit dem Namen "MetroShare" erstellen (Blank App)
      2). MainPage.xaml doppelklicken und in das Grid diesen xaml Quelltext einfügen:

      Quellcode

      1. <TextBox x:Name="TxtShare" HorizontalAlignment="Left" Margin="10,10,0,0" TextWrapping="Wrap" Text="Guten Morgen" VerticalAlignment="Top" Width="339"/>
      2. <Button x:Name="CmdShare" Content="Share!" HorizontalAlignment="Left" Margin="10,47,0,0" VerticalAlignment="Top" Click="CmdShare_Click_1" />

      3). Auf den Button doppelklicken
      4). Diesen Import durchführen: (einfach ganz oben drüber reinschreiben)

      VB.NET-Quellcode

      1. Imports Windows.ApplicationModel.DataTransfer

      und einen DateiTransferManager deklarieren:

      VB.NET-Quellcode

      1. Dim dataTransferManager As DataTransferManager

      5). Jetzt legen wir unsere App als Source App fest. Dafür tragen wir in den Button ein:

      VB.NET-Quellcode

      1. Me.dataTransferManager = dataTransferManager.GetForCurrentView()
      2. AddHandler dataTransferManager.DataRequested, New TypedEventHandler(Of DataTransferManager, DataRequestedEventArgs)(AddressOf Me.OnDataRequested)

      Jetzt kriegen wir natürlich einen Fehler, da die Share Methode selber noch nicht da ist. dafür kopiert ihr einfach diese Methode bei euch irgendwo in den Code und passt sie später an den kommentierten Stellen an.

      VB.NET-Quellcode

      1. Private Sub OnDataRequested(sender As DataTransferManager, e As DataRequestedEventArgs)
      2. Dim requestData As DataPackage = e.Request.Data
      3. requestData.Properties.Title = "titel" 'Hier den Titel eintragen
      4. requestData.Properties.Description = "Description" 'Die Beschreibung
      5. requestData.SetText(TxtShare.Text) 'Text zum Sharen
      6. End Sub

      6). Ausführen, ob alles gut funktioniert. Wenn nicht, einfach hier einen Beitrag schreiben.

      Alles zusammen sieht so aus:

      VB.NET-Quellcode

      1. Imports Windows.ApplicationModel.DataTransfer
      2. Public NotInheritable Class MainPage
      3. Inherits Page
      4. Dim dataTransferManager As DataTransferManager
      5. Private Sub CmdShare_Click_1(sender As Object, e As RoutedEventArgs)
      6. Me.dataTransferManager = DataTransferManager.GetForCurrentView()
      7. AddHandler DataTransferManager.DataRequested, New TypedEventHandler(Of DataTransferManager, DataRequestedEventArgs)(AddressOf Me.OnDataRequested)
      8. End Sub
      9. Private Sub OnDataRequested(sender As DataTransferManager, e As DataRequestedEventArgs)
      10. Dim requestData As DataPackage = e.Request.Data
      11. requestData.Properties.Title = "titel" 'Hier den Titel eintragen
      12. requestData.Properties.Description = "Description" 'Die Beschreibung
      13. requestData.SetText(TxtShare.Text) 'Text zum Sharen
      14. End Sub
      15. End Class


      Solltet ihr auch noch das Share Charm sofort anzeigen lassen wollen, einfach diese Zeile noch im Button als letztes einfügen:

      VB.NET-Quellcode

      1. dataTransferManager.ShowShareUI()



      Zeichnen:
      Spoiler anzeigen

      Eine richtige Möglichkeit zum Zeichnen gibt es noch nicht, daher habe ich einmal eine Region geschrieben, die zwar nicht gerade als sauber zu bezeichnen ist, aber sie funktioniert. Am Ende war ich sogar von der Schnelligkeit überrascht.
      Also zum Zeichnen wird als erstes dieser Import benötigt:

      VB.NET-Quellcode

      1. Imports Windows.UI.Xaml.Shapes

      Dann diese Region: (einfach unter "Inherits Page" kopieren und verkleiner mit dem Minus oben links)

      VB.NET-Quellcode

      1. #Region "Drawing Metro"
      2. Dim LastItem As Object 'Letztes hinzugefügtes Objekt
      3. Public Sub DrawLine(ByVal Surface As Object, ByVal Thickness As Integer, ByVal Alpha As Integer, ByVal red As Integer, ByVal green As Integer, ByVal blue As Integer, ByVal xPos1 As Double, ByVal yPos1 As Double, ByVal xPos2 As Double, ByVal yPos2 As Double)
      4. Dim myLine As New Line()
      5. myLine.Stroke = New SolidColorBrush(Windows.UI.Color.FromArgb(Alpha, red, green, blue))
      6. myLine.X1 = xPos1
      7. myLine.Y1 = yPos1
      8. myLine.X2 = xPos2
      9. myLine.Y2 = yPos2
      10. myLine.HorizontalAlignment = HorizontalAlignment.Left
      11. myLine.VerticalAlignment = VerticalAlignment.Center
      12. myLine.StrokeThickness = Thickness
      13. LastItem = myLine
      14. Surface.Children.Add(myLine)
      15. End Sub
      16. Public Sub DrawRectangle(ByVal Surface As Object, ByVal Alpha As Integer, ByVal red As Integer, ByVal green As Integer, ByVal blue As Integer, ByVal xPos1 As Double, ByVal yPos1 As Double, ByVal xPos2 As Double, ByVal yPos2 As Double)
      17. Dim myRect As New Windows.UI.Xaml.Shapes.Rectangle
      18. myRect.Margin = New Thickness(xPos1, yPos1, 0, 0)
      19. myRect.Width = xPos2 - xPos1
      20. myRect.Height = yPos2 - yPos1
      21. myRect.Fill = New SolidColorBrush(Windows.UI.Color.FromArgb(Alpha, red, green, blue))
      22. LastItem = myRect
      23. Surface.Children.Add(myRect)
      24. End Sub
      25. Public Sub DrawEllipse(ByVal Surface As Object, ByVal Alpha As Integer, ByVal red As Integer, ByVal green As Integer, ByVal blue As Integer, ByVal xPos1 As Double, ByVal yPos1 As Double, ByVal xPos2 As Double, ByVal yPos2 As Double)
      26. Dim myEllipse As New Windows.UI.Xaml.Shapes.Ellipse
      27. myEllipse.Margin = New Thickness(xPos1, yPos1, 0, 0)
      28. myEllipse.Width = xPos2 - xPos1
      29. myEllipse.Height = yPos2 - yPos1
      30. myEllipse.Fill = New SolidColorBrush(Windows.UI.Color.FromArgb(Alpha, red, green, blue))
      31. LastItem = myEllipse
      32. Surface.Children.Add(myEllipse)
      33. End Sub
      34. Public Sub DrawImage(ByVal Surface As Object, ByVal SourceObjekt As Image, ByVal xPos1 As Double, ByVal yPos1 As Double, ByVal xPos2 As Double, ByVal yPos2 As Double)
      35. Dim myImage As New Image
      36. myImage.Source = SourceObjekt.Source
      37. myImage.Margin = New Thickness(xPos1, yPos1, 0, 0)
      38. myImage.Width = xPos2 - xPos1
      39. myImage.Height = yPos2 - yPos1
      40. LastItem = myImage
      41. Surface.Children.Add(myImage)
      42. End Sub
      43. Public Sub Refresh(ByVal Element As Object)
      44. Element.Children.Clear()
      45. End Sub
      46. Public Sub RemoveLastItem(ByVal Container As Object)
      47. Container.Children.Remove(LastItem)
      48. End Sub
      49. #End Region

      Jetzt werde ich noch ein Anwendungsbeispiel für die bisher recht spärlichen Methoden zeigen. Als erstes brauchen wir natürlich eine Zeichenfläche. Ich verwende hier am liebsten das Canvas, damit wurde das Zeichnen auch getestet. Also schreibt man jetzt in das Standartmäßig erstellte Grid: (xaml Code)

      Quellcode

      1. <Canvas x:Name="ZeichenBrett" HorizontalAlignment="Left" Height="768" VerticalAlignment="Top" Width="1366"/>

      Also haben wir jetzt ein Canvas mit Namen "ZeichenBrett". Im Prinzip könnte man jetzt einfach "draw" irgendwo eingeben, einen der Vorschläge nehmen und die Parameter ausfüllen. Zum löschen der Objekte einfach Refresh(ZeichenBrett).
      Linie:

      VB.NET-Quellcode

      1. DrawLine(ZeichenBrett, Dicke, Transparenz, Rot, Grün, Blau, x1, y1, x2, y2)

      - Der erste Wert beschreibt den Container, auf dem gezeichnet wird
      - als nächstes die Dicke der Linie
      - Für die Transparenz wird meistens 255 eingesetzt, da die Linie dann voll gezeichnet wird.
      - dann ein RGB Wert für die Farbe
      - dann Start und Endpunkt
      Rechteck:

      VB.NET-Quellcode

      1. DrawRectangle(ZeichenBrett, Transparenz, Rot, Grün, Blau, x1, y1, x2, y2)

      - Die ersten Parameter: siehe Linie
      - Der erste Punkt ist die linke obere Ecke und er zweite die rechte untere
      Ellipse:

      VB.NET-Quellcode

      1. DrawEllipse(ZeichenBrett, Transparenz, Rot, Grün, Blau, x1, y1, x2, y2)

      - Siehe Linie
      Bilder:

      VB.NET-Quellcode

      1. DrawImage(ZeichenBrett, Ein anderes Bild desser Source dann verwendet wird, x1, y1, x2, y2)

      - Im xaml ein anderes Bild wie dieses hier erstellen und als Parameter den Namen des Bildes übernehmen. Das wird für die Source des zu zeichnenden Bildes benötigt:

      Quellcode

      1. <Image x:Name="Kreuz" Source="Assets/Logo.png" Visibility="Collapsed" />

      (nicht ins Canvas!!)

      Dann noch mit Refresh alle gezeichneten Sachen aus dem Canvas löschen


      Andere Threads zu Metro:
      - [Allgemein] Webbrowser programmieren in Visual Studio 2012 RC
      - [Allgemein] VS 2012 VB Metro - Image.Source zuweisen als UI.Xaml.Media.ImageSource
      - [VB 2012] My.Settings bei Metro Apps in VS 2012 Ultimate

      Dieser Beitrag wurde bereits 10 mal editiert, zuletzt von „Telcrome“ ()

      Gibt es einen Grund, dass du mit der ViewBox alles auf einer bestimmten Größe halten möchtest? Habe nie Metroapps gemacht, jedoch ist es wahrscheinlich vom Prinzip sehr ähnlich wie WPF und in WPF sehe ich dazu absolut rein gar keinen Grund. Im Gegenteil ist eher weniger optimal. Wie sieht es mit MVVM aus? Geht das Ganze zeug was es in WPF gibt auch hier? Sprich Commands, Styles, Templates, Bindings,...?
      Außerdem frage ich mich ob du das Prinzip von XAML-Designer verstanden hast? Das Prinzip von WPF ist nämlich zu 100% anders als WinForms. Und da Metroapps anscheinend praktisch gleich sind wie WPF(zumindest vom Styletechnischen) machst du da was falsch. Weil z.B. solche Dinge sollten in gutem XAML-Code niemals vorkommen:

      Quellcode

      1. Margin="41,26,0,0" VerticalAlignment="Top" Width="119" Click="BtnStart_Click_1"

      Das Erste wäre, dass dies zu 99% von nem Designer generiert wurde und das eben nicht verwendet werden sollte. Verwende pures XAML in Kombination mit Containern,... wie Grid, StackPanel, Canvas, DockPanel,...(oder natürlich auch eigenen wobei dies fortgeschrittenen Wissen beansprucht). In WPF bist du eigentlich von der Auflösung unabhängig und so sollte man auch die GUI's gestalten. Wenn Width dann in 90% der Fälle nur mit Bindings auf andere Controls... denn WPF funktioniert nunmal komplett anders als WinForms.
      Der nächste Punkt bei dem Code ist das Click Event. Im Gegensatz zu dem Punkt mit dem Designer ist dies kein absolutes No-Go aber sollte trotzdem nicht verwendet werden. Die ganzen Events sind leider noch von WinForms übrig geblieben und manchmal muss man sie auch verwenden. Aber ButtonClicks sollten eigentlich zu 100% durch Commands in Kombination mit MVVM ersetzt werden. Commands sind übersichtlicher, dynamischer,... und können sogar automatisch deinen Button ein und ausschalten usw. z.B. willst du nen Button ausschalten wenn wenn in ner ListBox nix ausgewählt ist. Dazu machste da meistens erstma nen SelectedIndexChanged(oder so ähnlich)-Event und dann braucht der Button natürlich auch noch nen EventHandler. Sprich ListBox_SelectedIndexChanged und ButtonClick EventHandler einfach irgendwo in nen Codebehind reingeklatscht. In WPF mit MVVM kannste erstma das Ganze Codebehind in beliebig viele ViewModel aufteilen. Außerdem kannst du über z.B. nen CanExecute-Delegate beim Command gleich den auswerten ob das bei der ListBox ausgewählt ist und der Button aktiviert sich automatisch. Dazu ist der Command zugleich auch nen ButtonClick-Event handler. Was übrig bleibt ist nen sauberes und strukturiertes ViewModel mit einem Command welcher alles erledigt.
      In WinForms oder auch bei falsch angewandter WPF -> Brainfuck.


      Opensource Audio-Bibliothek auf github: KLICK, im Showroom oder auf NuGet.
      @thefiloe
      ModernUI-Apps sollten zu 100% auf MVVM basieren. ALLE Templates von Microsoft direkt basieren nur auf MVVM.
      Eigentlich ist eine ModernUI-App nur WPF für Tablets.
      Und in der MSDN bei den Tutorials wird MVVM auch ganz groß geschrieben -> siehe Reversi-Spiele-App.

      @Telcrome
      Ich muss thefiloe Recht geben. Feste Größen sind ABSOLUT TABU in WPF/ModernUI-Anwendungen.
      Schau dir mal ein paar Tuts zum Thema MVVM an, und du wirst feststellen, dass das ein echt fantastisches Pattern ist :D

      Noch ein frohes neues Jahr,
      Julian
      @julian2704 na das ist doch mal erfreulich, dass man jetzt endlich mal getrost sagen kann, dass man MVVM benutzen MUSS. Bis jetzt gabs ja auch immer Gegenmeinungen welche z.B. sagen... bei kleinen Projekten gibts Ausnahmen...


      Opensource Audio-Bibliothek auf github: KLICK, im Showroom oder auf NuGet.