Saturday, May 11, 2013

Windows Store Split App Template an Echtdaten anbinden

Eines der Templates um eine Windows Store App zu erstellen ist das Split App (XAML) Template.

Dieses ist sofort lauffähig und liefert euch sofort Daten. Diese sind in der Applikation allerdings “harcoded”, das ist für die meisten Zwecke nicht wirklich brauchbar. Wir wollen nun gemeinsam etwas “Dynamik” in das Template bringen und Echtdaten, die frei zur Verfügung stehen anbinden.

Dazu erstelle ich zuerst einmal eine neue Windows Store Splitt App (XAML) und nenne diese SplitAppRealData, und zur Sicherheit lasse ich diese gleich einmal laufen, um die Demodaten "zu begutachten.

SNAGHTML904531b0image

Es gibt einige JSON Quellen, die Daten frei zur Verfügung stellen, eine davon ist die Flickr API. Diese werden wir in diesem Beispiel verwenden.

http://api.flickr.com/services/feeds/photos_public.gne?tags=surf,pipeline&tagmode=all&format=json&jsoncallback=?

Der erste Schritt ist dass wir C# Klassen zu dem JSON-Resultat benötigen ,diese lassen wir uns mit Hilfe der Webseite http://json2csharp.com/ erzeugen.

Dazu postet Ihr einfach das Resultat aus dem Browser auf die Webseite. Das Resultat sind dann folgende Klassen (die ich etwas angepasst habe, damit diese den allgmeinen C#-Coding Standards entsprechen):

    [DataContract()]
public class Media
{
[DataMember(Name = "m")]
public string PreviewUrl { get; set; }
}

[DataContract()]
public class Item
{
[DataMember(Name = "title")]
public String Title { get; set; }

[DataMember(Name = "link", IsRequired = true)]
public String Link { get; set; }

[DataMember(Name = "media")]
public Media Media { get; set; }

[DataMember(Name = "date_taken")]
public string Datetaken { get; set; }

[DataMember(Name = "description")]
public string Description { get; set; }

[DataMember(Name = "published")]
public string Published { get; set; }

[DataMember(Name = "author")]
public string Author { get; set; }

[DataMember(Name = "author_id")]
public string AuthorId { get; set; }

[DataMember(Name = "tags")]
public string Tags { get; set; }
}

[DataContract()]
public class RootObject
{
[DataMember(Name = "title", IsRequired = true)]
public String Title { get; set; }

[DataMember(Name = "link", IsRequired = true)]
public String Link { get; set; }

[DataMember(Name = "items", IsRequired = false)]
public Item[] Items { get; set; }
}

Jetzt ist es an der Zeit die Daten von Flickr zu holen und in dem Template anuzeigen. Dazu muß man die LoadState Methode der ItemsPage.xaml.cs Datei anpassen. Ich habe den “Default-Call” zu SampleDataSource.GetGroups auskommentiert. Stattdessen rufen wir eine Methode LoadItems auf. Diese wiederum ruft eine neue Methode SampleDataSource.GetJsonGroups, die danach implementiert wird.

        protected override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
{
// TODO: Create an appropriate data model for your problem domain to replace the sample data
//var sampleDataGroups = SampleDataSource.GetGroups((String)navigationParameter);

LoadItems();
}

private async Task LoadItems()
{
string url =
"http://api.flickr.com/services/feeds/photos_public.gne?tags=surf,pipeline&tagmode=all&format=json&jsoncallback=?";
var sampleDataGroups = await SampleDataSource.GetJsonGroups(url);

this.DefaultViewModel["Items"] = sampleDataGroups;
}
 

Die Methode  GetJsonGroups erledigt die eigentliche Arbeit:



  • Den WebRequest usführen
  • Das Resultat in einen MemoryStream schreiben
  • Deserialisieren des JSON-Strings in die C# Klassen
  • Zurückgeben der Enumeration
        public static async  Task<IEnumerable<Item>> GetJsonGroups(string url)
{
try
{
var client = new HttpClient();
var result = await client.GetStringAsync(new Uri(url, UriKind.Absolute));

MemoryStream stream = new MemoryStream();
//Usually 0 and result.length, BUT
//Flickr adds a ( at the beginning and a ) at the end
stream.Write(Encoding.UTF8.GetBytes(result), 1, result.Length - 2);
stream.Position = 0;
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(RootObject));

var rootObject = (RootObject)ser.ReadObject(stream);

return rootObject.Items.ToList();
}
catch (Exception ex)
{
Debug.WriteLine("!EXCEPTION in GetJsonGroups!");
throw;
}
}

Und das war es dann auch schon, wenn man die App laufen lässt, erhält man schon ein durchaus erfreuliches Resultat:


imageimage


Um das Resultat zu verbessern, muss noch das Standard250x250ItemTemplate in StandardStyles.xaml minimal angepasst werden.

    <DataTemplate x:Key="Standard250x250ItemTemplate">
<Grid HorizontalAlignment="Left" Width="250" Height="250">
<Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}">
<Image Source="{Binding Media.PreviewUrl}" Stretch="UniformToFill" AutomationProperties.Name="{Binding Title}"/>
</Border>
<StackPanel VerticalAlignment="Bottom" Background="{StaticResource ListViewItemOverlayBackgroundThemeBrush}">
<TextBlock Text="{Binding Title}" Foreground="{StaticResource ListViewItemOverlayForegroundThemeBrush}" Style="{StaticResource TitleTextStyle}" Height="60" Margin="15,0,15,0"/>
<TextBlock Text="{Binding Author}" Foreground="{StaticResource ListViewItemOverlaySecondaryForegroundThemeBrush}" Style="{StaticResource CaptionTextStyle}" TextWrapping="NoWrap" Margin="15,0,15,10"/>
</StackPanel>
</Grid>
</DataTemplate>

Wie man sieht ist es relativ einfach das Standard-Template so aufzubohren, dass es sehr schnell Resultate liefert.

Monday, May 6, 2013

Windows Store App - Application Themes, Dark und Light

Vor kurzem hatte ich das Problem, dass in einem Windows Store Kundenprojekt das User Interface umgetauscht werden sollte.

Die Business Applikation war nahezu fertig und plötzlich sollte die APP von quasi dunkel nach sehr hell wechseln.
Zum Glück war das innerhalb von Minuten erledigt. Dank den beiden Application Themes: Dark und Light.

Das würde z. B. so, oder eben so aussehen:

image

Am Einfachsten verändert man die Einstellung in der App.xaml Datei, indem Ihr den

RequestedTheme="Light" oder  RequestedTheme="Dark" setzt.

image

Falls Ihr das nicht im App.xaml machen möchtet, dann klappt das auch per Code im Konstruktor der App.xaml.cs
(ACHTUNG: später klappt das nicht mehr).

RequestedTheme = ApplicationTheme.Light;

Vorsicht: Das klappt auch nicht, wenn eure Anwender im high contrast mode arbeiten…

Die Definitionen für die Themes findet Ihr übrigens auf eurer Festplatte:

"c:\Program Files (x86)\Windows Kits\8.0\Include\WinRT\Xaml\Design\themeresources.xaml"

Ihr könnt das Aussehen eures Fensters übrigens auch in Visual Studio direkt testen, ohne die Applikation laufen zu lassen, und zwar über das (Menü Design->) Device Fenster.

image

image

Ich wünsche euch Viel Spass mit den beiden Application Themes!

CSharpCodeFormatter