Von
Rina Ahmed
15. May 2013 16:00
In diesem Post wird gezeigt, wie man gewährleisten kann, dass Windows Store Apps an einem bestimmten Datum veröffentlicht werden.
[More]
Von
Christian Vorhemus
1. May 2013 11:58
In diesem Tutorial soll gezeigt werden, wie Daten in einer Windows 8 App mittels IndexedDB gespeichert und wieder ausgelesen werden können. Als Beispiel dient dazu eine einfache Benutzerverwaltungs-App, mit der Benutzer angelegt und wieder gelöscht werden. Ein kurzer Überblick über IndexedDB Im Zuge der immer vielfältigeren Möglichkeiten, die mit klassischen Webapplikationen geschaffen werden können, wurden auch Stimmen nach effizienten clientseitige Speichermöglichkeiten laut. Bis dato war die persistente Datenspeicherung hier so gut wie gar nicht möglich: Lediglich Cookies erlaubten das Schreiben und Lesen von Parametern. Diese waren aber allein schon aufgrund der geringen erlaubten Speichergröße maximal für einige zu speichernden Einstellungen auf Webseiten zu gebrauchen. Mozilla wagte hier einen Vorstoß und führte als eine der Ersten für ihren Browser eine Index-basierte Datenbank ein. Schließlich wurde die Spezifikation für eine solche Datenbank vor gut einem Jahr vom W3-Konsortium verabschiedet und ist offiziell Bestandteil von HTML5. Verwendet werden kann IndexedDB nicht nur mit Browsern wie Internet Explorer 10, Chrome oder Firefox sondern dank der weitreichenden HTML5-Unterstützung auch mit Windows 8! Schritt 1: Projekt öffnen und vorbereiten Zunächst öffnen wir in Visual Studio 2012 ein neues Projekt und wählen den Unterpunkt JavaScript > Windows Store > Navigations-App aus. (Hinweis: Wer neu in der Welt der HTML5/Javascript-Apps ist, mag sich als Einstieg vielleicht zuvor dieses Tutorial ansehen) Ist das Projekt angelegt, navigieren wir in den Ordner pages/home und öffnen home.html. Dort ändern wir zunächst den style von ui-dark.css auf ui-light.css, schreiben im span-tag der Klasse “pagetitle” “Benutzerverwaltung” statt “Willkommen bei DBSample” und löschen die Zeile “Hier Inhalt einfügen” zwischen den <p></p>-Tags. Als nächstes fügen wir die AppBar hinzu, die sich bei einem Rechtsklick in die App bzw. auf Touch-Devices von einer Wischbewegung vom unteren Rand nach oben öffnet. Dazu kopieren wir folgenden Code und fügen ihn in die home.html-Datei knapp über dem </body>-Tag ein: <div id="appbar" data-win-control="WinJS.UI.AppBar">
<button data-win-control="WinJS.UI.AppBarCommand" data-win-options="{id:'removeUser',
label:'Löschen', icon:'delete'}" type="button"></button>
<button data-win-control="WinJS.UI.AppBarCommand" data-win-options="{id:'addUser', label:'Neu', icon:'add'}" type="button"></button>
</div>
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Wenn wir nun auf F5 klicken um die App zu starten und danach mit dem rechten Maustaste in die App klicken, sollte sich die noch funktionslose AppBar öffnen. Um die AppBar zu stylen, können wir uns übrigens der .win-appbar-property bedienen. Um den AppBar-Hintergrund grau zu färben, kopiere man nachfolgenden Code in die home.css-Datei:
.win-appbar {
background-color: #CCCCCC;
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Im nächsten Schritt legen wir ein Fenster an, das sich öffnet, wenn der User auf den “Neu”-Button in der AppBar klickt. Dazu schreiben wir ein <div>, in dem sich Text-inputs sowie Buttons befinden. Diesen Code fügen wir gleich nach dem <body>-Tag in home.html hinzu:
<div id="addDiv">
<h2>Neuen Benutzer hinzufügen</h2><p></p>
<table>
<tr><td>Name:</td><td><input type="text" id="username" /></td></tr>
<tr><td>Alter:</td><td><input type="number" id="age"/></td></tr>
<tr><td>Typ:</td><td><select id="type"><option>User</option><option>Administrator</option>
</select></td></tr>
</table>
<p></p>
<input type="button" id="addEntry" value="Eintragen"/> <input type="button" id="close" value="Schließen"/>
</div>
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Um das <div> mittig auszurichten, kopiere man folgenden Code in die home.css-Datei:
#addDiv {
color:black;
display:none;
height:250px;
position: absolute;
width:530px;
z-index: 50;
border: 5px solid grey;
top: 50%;
left: 50%;
margin-top: -125px;
margin-left: -287px;
background-color:white;
font-size:20px;
padding-top:20px;
padding-left:20px;
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Das div wird zunächst nicht angezeigt (display:none;), kümmern wie uns nun um den Öffnen/Schließen-Mechanismus. Dazu öffnen wir die home.js-Datei. In Zeile 7 sehen wir den Eintrag “ready: function (element, options)”. In dieser Funktion wird die Seite initialisiert, hier werden wir auch unsere EventListener anlegen, damit bei Klicks auf die Buttons der AppBar das Fenster geöffnet wird. In dieser Funktion legen wir die folgenden drei EventListener an:
document.getElementById("addEntry").addEventListener("click", addEntry);
document.getElementById("close").addEventListener("click", closeWindow);
document.getElementById("addUser").addEventListener("click", openWindow);
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Wird auf den Button mit der ID “addEntry” geklickt, wird die Funktion addEntry ausgeführt; Äquivalentes gilt für die anderen zwei Listener.
Legen wir nun die openWindow() und closeWindow() Funktionen an. Wir kopieren den nachfolgenden Code und fügen ihn kurz nach der WinJS.UI.Pages.define-Funktion ein.
function openWindow() {
document.getElementById("appbar").winControl.hide();
var elm = document.getElementById("addDiv");
elm.style.display = "block";
WinJS.UI.Animation.fadeIn(elm);
}
function closeWindow() {
var elm = document.getElementById("addDiv");
elm.style.display = "none";
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Unsere home.js Datei sollte bis jetzt wie folgt aussehen:
Detail am Rande: In der openWindow-Funktion bedienen wir uns der von WinJS bereitgestellten fadeIn-Funktion um einen Fade-Effekt zu erzeugen. Eine Fade-Out-Animation gibt es auch – fadeOut heißt hier das Pendant.
Wenn wir nun auf den “Neu”-Button in unserer AppBar klicken, wird unser div geöffnet, die sich zentriert in der Bildschirmmitte befindet:
Schritt 2: Datenbank anlegen
Mit IndexedDB werden Objekte in Form eines key-value-pairs gespeichert, am häufigsten wird zu diesem Zweck die JSON- Notation verwendet. Würden wir mit einer relationalen Datenbank arbeiten, müssten wir für unsere Benutzerverwaltung zunächst die Datenbank erstellen. Das könnte für relationale Datenbanken in MySQL etwa so aussehen:
CREATE DATABASE userDatabase;
In unserer IndexedDB legen wir eine Datenbank wie folgt an:
var request = window.indexedDB.open("userDatabase ", 1);
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Der erste Parameter ist der Datenbankname, der zweite gibt die Versionsnummer an (immer wenn sich das Datenbankschema ändert, muss sich auch die Versionsnummer ändern). Die open()-Funktion selbst retourniert ein Request-Objekt, das mehrere Zustände beschreiben kann: Success, Error, Blocked und UpgradeNeeded wobei letzterer Zustand immer dann aufgerufen wird, wenn sich die Versionsnummer ändert.
Um die Datenbank anlegen bzw öffnen zu können, fügen wir folgende Funktion kurz oberhalb von openWindow in home.js ein:
var db = null;
function openDatabase() {
var dbRequest = window.indexedDB.open("userDatabase", 1);
dbRequest.onerror = function () { console.log("Fehler beim Erstellen der Datenbank"); };
dbRequest.onblocked = function () { console.log("Datenbank blockiert"); };
dbRequest.onsuccess = function (evt) {
db = evt.target.result;
showEntries();
};
dbRequest.onupgradeneeded = function (evt) {
if (db) {
db.close();
}
db = evt.target.result;
var txn = evt.target.transaction;
var bookStore = db.createObjectStore("userlist", { keyPath: "id", autoIncrement: true });
bookStore.createIndex("username", "username", { unique: false });
txn.oncomplete = function () { };
};
}
function showEntries() {
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Die openDatabse()-Funktion soll bei der Initialisierung der Seite aufgerufen werden, wir fügen daher den Eintrag
openDatabase();
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
kurz unterhalb des EventListeners
document.getElementById("addUser").addEventListener("click", openWindow);
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
hinzu.
In relationalen Datenbanken würden wir im nächsten Schritt das Datenbankschema in SQL anlegen, was (in MySQL) etwa so aussehen könnte:
CREATE TABLE user (
id INT PRIMARY KEY,
username VARCHAR(40) ,
age INT,
type ENUM(‘Administrator’, ‘User’)
);
Mit diesem Code legen wir also eine Tabelle an, in die wir nun Daten ablegen können. Mit IndexedDB kreieren wir im Unterschied dazu Objekt-Storages. Das ist nichts anderes als ein Speicherplatz mit einem zugewiesenen Namen, in den Objekte (als key-value-pair) abgelegt werden können. Ein “richtiges” Schema für Tabellen wie bei relationalen Datenbanken gibt es hierbei nicht. Der entsprechende Code um ein solches Objekt-Storage für die Benutzerverwaltung anzulegen, könnte in etwa wie folgt aussehen:
db.createObjectStore("users",{keyPath: "id"});
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
keypath gibt hierbei jenen value an, mit der der Datensatz eindeutig identifiziert werden kann.
Unsere Datenbank steht nun bereit um Daten aufzunehmen, fügen wir nun eine Funktion addEntry() hinzu. Diese können wir oberhalb von openDatabase einfügen:
var user = new WinJS.Binding.List();
WinJS.Namespace.define("UserList", {
user: user
});
function addEntry() {
var username = document.getElementById("username").value
var age = document.getElementById("age").value
var type = document.getElementById("type").value
var id = 0;
if (user.length != 0) {
user.dataSource.itemFromIndex(user.length - 1).done(function (item) {
id = item.data.id + 1;
});
}
var item = { "id": id, "username": username, "age": age, "type": type, "picture": "/images/user.png" };
var transaction = db.transaction("userlist", "readwrite");
var addRequest = transaction.objectStore("userlist").add(item);
addRequest.onsuccess = function (evt) {
user.push(item);
}
closeWindow();
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Um Daten löschen zu können, legen wir nun in der home.js-Datei einen weiteren EventListener in der ready-Funktion an:
document.getElementById("removeUser").addEventListener("click", deleteEntry);
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
… die zugehörige deleteEntry()-Funktion sieht so aus, diese kopieren wir unter die addEntry-Funktion:
function deleteEntry() {
var listView = document.getElementById("itemsListView").winControl;
listView.selection.getItems().done(function (currentSelection) {
currentSelection.forEach(function (selectedItem) {
var dbKey = selectedItem.data.id;
var listViewKey = selectedItem.key;
var transaction = db.transaction("userlist", "readwrite");
var deleteRequest = transaction.objectStore("userlist").delete(dbKey);
deleteRequest.onsuccess = function () {
user.dataSource.remove(listViewKey);
}
deleteRequest.onerror = function () {
}
});
});
document.getElementById("appbar").winControl.hide();
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Schritt 3: ListView erstellen
Im letzten Schritt haben wir unter anderem die Zeile
var user = new WinJS.Binding.List();
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
hinzugefügt. Diese so definierte Liste “user” verwenden wir, um darin alle Benutzer zu speichern, die wir aus der Datenbank auslesen um diese schließlich zu unserer ListView hinzuzufügen. Die ListView selbst ist nichts anderes als eine von WinJS zur Verfügung gestellte control um eine Ansammlung an Items im Sinne des "Modern UI” anzuzeigen.
Um unsere Liste “user” beim Initialisieren zunächst mit den Daten aus der Datenbank zu füllen, ersetzen wir die leere showEntries()-Funktion, die sich bereits in unserer home.js-Datei befindet, mit folgendem Code:
function showEntries() {
if (db) {
var request = [];
var transaction = db.transaction("userlist", "readonly");
var store = transaction.objectStore("userlist");
var index = store.index("username");
index.openCursor().onsuccess = function (event) {
var cursor = event.target.result;
if (cursor) {
user.dataSource.insertAtEnd(null, cursor.value);
cursor.continue();
}
};
}
}
Nun müssen wir unsere Liste “user” allerdings auch anzeigen. Zu diesem Zweck fügen wir den folgenden Code in unsere home.html-Datei kurz nach “<section aria-label="Main content" role="main">” hinzu:
<div id="mediumListIconTextTemplate" data-win-control="WinJS.Binding.Template" style="display: none">
<div class="mediumListIconTextItem">
<img src="#" class="mediumListIconTextItem-Image" data-win-bind="src: picture" />
<div class="mediumListIconTextItem-Detail">
<b>Username:</b> <span data-win-bind="innerText: username"></span><br />
<b>Alter:</b> <span data-win-bind="innerText: age"></span><br />
<b>Accounttyp:</b> <span data-win-bind="innerText: type"></span>
</div>
</div>
</div>
<div id="itemsListView" data-win-control="WinJS.UI.ListView"
data-win-options="{itemDataSource : UserList.user.dataSource,
itemTemplate: select('#mediumListIconTextTemplate')}">
</div>
Hier wird die ListView angelegt und mit einem entsprechenden Template versehen, sodass unsere Daten formatiert ausgegeben werden. Wenn wir die App testen, auf “Neu” klicken und einen Benutzer anlegen, können wir schon Einträge speichern, allerdings sieht der Eintrag noch etwas unfömig aus. Um das zu ändern, fügen wir zunächst folgendes Bild in den /image-Folder hinzu:
Außerdem fügen wir folgenden Code in unsere home.css ein:
#itemsListView {
height: calc(100% - 80px);
width:calc(100% - 90px);
border: 0px solid red;
}
#itemsListView .win-container:not(.footprint):not(.hover)
{
background-color: transparent;
color:black;
border: 1px solid gray;
}
.mediumListIconTextItem
{
width: 282px;
height: 70px;
padding: 5px;
overflow: hidden;
display: -ms-grid;
}
.mediumListIconTextItem img.mediumListIconTextItem-Image
{
width: 60px;
height: 60px;
margin: 5px;
-ms-grid-column: 1;
}
.mediumListIconTextItem .mediumListIconTextItem-Detail
{
margin: 5px;
-ms-grid-column: 2;
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Mit diesem Schritt sind wir bereits fertig: Wir können nun Benutzer hinzufügen indem wir in der AppBar auf “Neu” klicken. Wenn wir Benutzer löschen wollen, klicken wir mit der rechten Maustaste auf die jeweiligen Einträge um sie auszuwählen und dann nochmals mit der rechten Maustaste um auf den “Löschen”-Button klicken zu können.
Ein nettes Feature wäre noch, wenn sich bei einer Auswahl an Einträgen die AppBar automatisch öffnet, diese Funktion fügen wir im finalen Schritt 4 noch hinzu.
Schritt 4: Öffnen der AppBar durch selectionchanged-Events
Zunächst fügen wir wieder einen EventListener in der ready-Funktion in home.js ein:
document.getElementById("itemsListView").winControl.addEventListener("selectionchanged", changedSelection);
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Danach fügen wir die nachfolgende changedSelection-Funktion zB unterhalb von deleteEntry hinzu:
function changedSelection(eventObject) {
document.getElementById("appbar").winControl.show();
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
In Worten gesprochen passiert hier folgendes: Immer dann, wenn sich die aktuelle Auswahl (Rechtsklick) der itemsListView ändert, öffnet sich die AppBar.
Den Quellcode dieses Projekts gibt es auf http://www.wissen-kompakt.at/codefest/DBSample.zip zum Download!
Los gehts!
Dieses Tutorial ist nur ein Einstiegspunkt für weitere eigene Entwicklungen. Die Möglichkeiten, diese App zu erweitern sind unbegrenzt und reichen zB von einem FilePicker, um statt dem User-Platzhalter-Icon Fotos von Benutzern zu speichern, bis hin zu automatischer Datensynchronisation, um auf allen Geräten stets den gleichen Datenstand zu haben.
Nur empfehlen kann man abschließend die umfangreichen Dokumentationen und Codebeispiele auf msdn.microsoft.com, die einen tieferen Einblick in die Materie bieten.
Von
Toni Pohl (Gastblogger)
23. April 2013 07:15
Wie in “OfficeApps entwickeln-Teil 5 Wie bekommen ich meine App in den Office Store” beschrieben, werden Apps für Office und SharePoint 2013 im SellerDashboard in den Office Store von Microsoft eingestellt. Im SellerDashboard gibt es seit April eine Neuerung: Beim Hinzufügen einer neuen App prüft das Dashboard, ob mit dem verwendeten Microsoft Konto eine gültige Office 365-Lizenz verknüpft ist. Wie man diese verknüpft, zeigen wir hier.
[More]
Von
Toni Pohl (Gastblogger)
22. April 2013 11:09
Wenn man eine neue App für Office 2013 oder SharePoint 2013 entwickelt hat, ab damit in den Microsoft Office Store! Was benötigt der Entwickler dazu? Eine fertige App (je nach Typ der App nur die Manifest-Datei, oder das app-Paket), ein Microsoft Konto und eine Registrierung im Microsoft Sellerdashboard. Wie das funktioniert, zeigen wir hier.
[More]
Von
Toni Pohl (Gastblogger)
1. April 2013 00:05
Das Osterwochenende war mit dem Winterwetter perfekt geeignet, vorm PC zu sitzen und sich mit Lernen und Code zu befassen – wie Weihnachten, nur stand Osterjause statt Kekse auf dem Programm. Und natürlich Visual Studio und SharePoint 2013. Ein Thema, mit dem ich mich wieder näher befasst habe, ist die Entwicklung von SharePoint 2013 Apps und zwar mit der dafür erforderlichen Authentifizierung.
[More]
Von
Christian Vorhemus
20. March 2013 15:05
Man nehme eine Portion Motivation und eine gute Entwicklungsumgebung (Visual Studio 2012), würze alles mit einer Prise Kreativität und fertig ist die Windows 8 App! In dieser Kochshow sollen Konzepte und Sourcode gezeigt werden, mit denen Apps für Windows 8 sehr schnell und einfach in HTML5/Javascript geschrieben werden können. Voraussetzung für dieses kleine Tutorial sind nur Basiskenntnisse in HTML und Javascript, Erfahrung in höheren Programmiersprachen ist nicht nötig. Ziel ist es, dem geneigten Leser einen Überblick über die Entwicklung von Windows 8 Apps in HTML und Javascript zu verschaffen, einige Hintergrundinformationen zu Windows 8 typischen Funktionalitäten zu liefern und Code vorzustellen, mit dem bereits die ersten Apps erstellt werden können. Wir halten uns in diesem Tutorial an folgendes Rezept: Die Struktur eines Projekts Anonyme Funktionen und WinJS Formelemente, Event-Listener und Debugging Navigation und Seiten Pimp your site with CSS Die weiteren Schritte Die Struktur eines Projekts Um den Aufbau einer App gleich am Praxisobjekt erforschen zu können, öffnen wir Visual Studio 2012 (Visual Studio Express 2012 für Windows 8 kann hier heruntergeladen werden), klicken oben links auf Datei > Neu > Projekt. Im nun erscheinenden Fenster wählen wir links im Menü “installiert” den Unterpunkt “Vorlagen” und als Sprache “JavaScript” aus. Danach klicken wir auf “Windows Store” und wählen “Navigations-App”. Weiter unten in diesem Fenster können wir im Textfeld “Name” unser Projekt noch benennen und mit einem Klick auf “OK” tauchen wir bereits ein, in die Welt der App-Entwicklung. Nach kurzer Ladezeit wird automatisch die default.js-Datei im Codefenster angezeigt, rechts daneben sehen wir den Projektmappen-Explorer, in dem die verschiedensten Ordner und Dateien unseres Projekts angezeigt werden. Apps können aus mehreren Seiten bestehen, etwa einer Hauptseite mit mehreren Items und Unterseiten, auf denen detaillierte Infos zu den Items eingeblendet werden. Die Seiten einer App befinden sich im Ordner “pages”, wobei jede Seite einen eigenen Unterordner erhält. Standardmäßig wird für uns gleich eine erste Seite erstellt, die “home” lautet. Eine Seite wiederum besteht aus 3 Dateien: Eine HTML-Datei, eine CSS-Datei und eine JS-Datei. Während HTML und CSS für das Design zuständig sind (ähnlich wie XAML-files) befindet sich die Steuerungslogik in den JS-Dateien (ähnlich wie die “code behind”-Dateien in C#). Wenn ein Benutzer unsere App öffnet, gelangt er aber nicht gleich auf unsere home.html-Seite, sondern stets auf default.html. In dieser Datei kann selbst Inhalt stehen, oder auf eine andere Seite verwiesen werden. Dies passiert mit folgendem Code: 1: <div id="contenthost" data-win-control="Application.PageControlNavigator"
2: data-win-options="{home: '/pages/home/home.html'}"></div>
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Zwei Dinge sind hier interessant: Zum einen die data-win-control property, zum anderen die data-win-options property. Mittels data-win-control weisen wir unserem <div>-Element eine spezielle Windows 8 spezifische Eigenschaft zu – in diesem Fall soll das <div> als Navigationselement dienen. Es existieren eine Reihe an vordefinierten controls, die unsere leeren <div>-Tag wie durch Zauberhand in allerlei nützliche Steuerungselemente verwandeln, zum Beispiel können durch ein control aus einem <div> rating-Sternen erzeugt werden, was mit folgendem Code funktioniert:
1: <div data-win-control="WinJS.UI.Rating"></div>
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Mit data-win-options werden weitere Optionen für den in data-win-control definierten control angegeben. In unserem Beispiel wird hier auf die Seite “home” verwiesen, die sich im Ordner “/pages/home/home.html” befindet.
Im Ordner css und im Ordner js befinden sich Dateien, die den Namen “default” tragen. Hier können Funktionen bzw. Styles definiert werden, die für die gesamte App gültig sind. Ein Beispiel dafür sind App-Bars: Die App-Bar soll auf jeder Unterseite meiner App erscheinen, sobald ich die rechte Maustaste klicke, daher definiere ich sie in meiner default.html. Zusammenfassend lässt sich also sagen: default.html sowie die im Ordner js befindliche default.js und die im css-Ordner befindliche default.css definieren den “Rahmen” und das Layout, das für alle Unterseiten der App gültig ist. Seitenspezifische styles werden in den im Ordner “pages” befindlichen css-Seiten definiert.
… und wie in allen App-Projekten, findet sich auch in einem JavaScript-Projekt die Datei package.appmanifest in der unter anderem die Hintergrundfarbe für den SplashScreen vergeben wird oder ausgewählt werden kann, welche Funktionen die App nutzen darf (Internetverbindung, Kamera, Mikrofon, …).
Anonyme Funktionen und WinJS
Werfen wir gleich einen Blick in die JS-Datei unserer home-Seite: Durch einen Doppelklick auf die entsprechende Datei können wir uns den Code anzeigen lassen:
Wir sollten folgenden Code sehen:
1: (function () {
2: "use strict";
3:
4: WinJS.UI.Pages.define("/pages/home/home.html", {
5: // Diese Funktion wird immer aufgerufen, wenn ein
6: // Benutzer zu dieser Seite wechselt. Sie
7: // füllt die Seitenelemente mit den Daten der App auf.
8: ready: function (element, options) {
9: // TODO: Die Seite hier initialisieren.
10: }
11: });
12: })();
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Hier wird eine (anonyme) Funktion definiert, die automatisch aufgerufen wird, wenn der User die Seite home.html anzeigen lässt. Mit den zwei Wörtern “use strict” wird definiert, dass unser Code im “strict mode” ausgeführt wird und damit bestimmte Regeln eingehalten werden müssen, damit der Code kompiliert werden kann (zB müssen alle Variablen mit dem Schlüsselwert var deklariert werden, bevor ihnen ein Wert zugewiesen werden kann).
In Zeile 4 wird auf WinJS verwiesen. WinJS ist eine Javascript-Bibliothek die eine Reihe an Funktionalitäten zur Verfügung stellt um uns die Arbeit zu erleichtern. Hier wird eine PageControl definiert, damit wir – vereinfacht gesagt – mit unserer home.html-Seite interagieren können.
In Zeile 8 befindet sich die Funktion ready. Code, der in dieser Funktion steht wird aufgerufen, während die Seite geladen wird. Das bedeutet, hier sollten zB Event-Listener (dazu siehe sogleich) definiert werden.
Formelemente, Event-Listener und Debugging
Die Grundfunktionalität einer jeden App ist es, die Aktionen, die ein Benutzer ausführt aufzufangen und entsprechende weitere Schritte zu setzen. Immer wenn ein User auf einen Button klickt oder eine Wischgeste ausführt, möchten wir diese Aktionen empfangen können, und auf die Eingaben reagieren. Wie in vielen anderen Frameworks, wird auch für Windows 8 das Konzept der Event-Listener verwendet, um Eingaben zu registrieren.
Wechseln wir zurück in Visual Studio und wagen wir uns an die erste simple Interaktion, die wir implementieren: Immer ein ein User auf einen Button klickt, soll ein Eintrag in die Javascript-Konsole geschrieben werden.
Da die HTML-Seiten das User-Interface darstellen, legen wir unseren Button auch in der home.html Datei an. Dazu löschen wir den Eintrag
27: <p>Hier Inhalt einfügen</p>
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
aus Zeile 27 und fügen stattdessen folgenden Code ein:
27: <button id="beispielbutton1">Beispielbutton</button>
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Der <button></button> Tag definiert einen simplen Button der mehr oder weniger nur aus einem weißen Rechteck mit Text besteht. Äußert wichtig ist für unsere Zwecke die property id, mit der unser Element für den Event-Listener eindeutig identifizierbar wird.
Wer eine schnelle Übersicht sucht, welche Elemente eingefügt werden können, möge in der Menüzeile auf “Ansicht” klicken und dann “Werkzeugkasten” auswählen.
Es öffnet sich daraufhin ein Fenster mit einer Auswahl an Formelementen, die mit einem Doppelklick auf das jeweilige Objekt in die App eingefügt werden können.
In der Regel möchten wir nun auch gerne sehen, wie unsere Button später in der App aussehen wird. Um die App anzuzeigen, klicken wir im oberen Menü auf “Lokaler Computer”, woraufhin ein (schwarzes) Fenster mit einem weißen durchkreuzten Rechteck angezeigt wird – der Splashscreen – und kurze Zeit darauf unsere home.html-Seite erscheint, die in etwa so aussieht:
Um die App zu schließen und zu Visual Studio zurückzukehren, fahren wir entweder mit der Maus auf die obere Kante und ziehen die App mit gedrückter Maustaste nach unten oder brechen die Ausführung mit Alt+F4 ab.
Wenn wir in Visual Studio zurückkehren, sehen wir anhand des roten Balkens am unteren Bildschirmrand, dass das Debugging noch läuft. Um dies zu beenden wählen wir entweder den Shortcut Shift+F5 oder klicken im oberen Menü auf “Debugging beenden”
Im nächsten Schritt fügen wir nun den Event-Listener hinzu. Hierbei handelt es sich um Steuerungslogik und diese wird in Javascript-files definiert. Wir wechseln daher in home.js und fügen in der ready-Funktion folgenden Code hinzu:
1: var button1 = document.getElementById("beispielbutton1");
2: button1.addEventListener("click", buttonClick, false);
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
In Zeile 1 greifen wir mittels document.getElementById() auf unseren Button zu und speichern das so erhaltene button-Objekt in der Variable button1. In Zeile 2 fügen wir unserem Button aus der home.html-Datei einen Event-Listener hinzu: Im ersten Argument dieser Funktion definieren wir, auf welches Event wir achten: “click”, also ein Mausklick bzw. ein Fingertab bei Touchscreens. Das zweite Argument gibt an, welche Funktion bei einem Klick auf den Button ausgeführt werden soll: “buttonClick” – diese Funktion müssen wir noch definieren. Im dritte Argument wird definiert, ob “capture” aktiviert werden soll (für dieses Beispiel nicht notwendig, daher false).
Wir haben nun definiert, dass mit einem Klick auf den Button mit der ID “beispielbutton1” die Funktion “buttonClick” aufgerufen werden soll. Diese Funktion müssen wir nun ebenfalls im home.js-file definieren. Unser Datei home.js sieht damit insgesamt wie folgt aus:
1: (function () {
2: "use strict";
3:
4: WinJS.UI.Pages.define("/pages/home/home.html", {
5: ready: function (element, options) {
6: var button1 = document.getElementById("beispielbutton1");
7: button1.addEventListener("click", buttonClick, false);
8: }
9: });
10:
11: function buttonClick() {
12: console.log("Auf Button geklickt");
13: }
14:
15: })();
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
In Zeile 12 definieren wir, dass der Text “Auf Button geklickt” in die Javascript-Konsole geschrieben werden soll. Wenn wir nun die App starten und einige Male auf den Button klicken, die App danach schließen und zurück in Visual Studio wechseln, sollte in unserer Konsole nun entsprechend oft der Text angezeigt werden:
Wer bereits öfter in Javascript entwickelt hat, hat vielleicht des Öfteren die alert()-Funktion zum Debuggen verwendet. Das ist zwar eine relativ unschöne Methode, ist für schnelles Auffinden von Fehlern im laufenden Betrieb dennoch manchmal sinnvoll. In Windows 8 gibt es die alert()-Funktion nicht, wir können und diese jedoch sehr schnell selbst basteln, indem wir unterhalb der buttonClick-Funktion folgenden Code einfügen:
1: function alert(text) {
2: var messagedialogpopup = new Windows.UI.Popups.MessageDialog(text, "Überschrift");
3: messagedialogpopup.showAsync();
4: }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Wir ersetzen nun den console-Eintrag in der buttonClick-Funktion durch einen Aufruf der alert()-Funktion sodass die gesamte home.js-Datei wie folgt aussieht:
1: (function () {
2: "use strict";
3:
4: WinJS.UI.Pages.define("/pages/home/home.html", {
5: ready: function (element, options) {
6: var button1 = document.getElementById("beispielbutton1");
7: button1.addEventListener("click", buttonClick, false);
8: }
9: });
10:
11: function buttonClick() {
12: alert("Auf Button geklickt");
13: }
14:
15: function alert(text) {
16: var messagedialogpopup = new Windows.UI.Popups.MessageDialog(text, "Überschrift");
17: messagedialogpopup.showAsync();
18: }
19:
20: })();
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Wenn wir nun die App starten und auf den Button klicken, erscheint ein MessageDialog. Wir müssen nun nicht zurück in Visual Studio wechseln, wenn wir uns zB die aktuelle Variablenbelegung ansehen wollen, sondern können uns alle möglichen Infos direkt in der App anzeigen lassen:
Navigation und Seiten
Bisher haben wir alle Aktionen auf unserer home-Seite ausgeführt ohne diese zu verlassen. Bei größeren Projekten ist es rein aus strukturellen Gründen besser, mehrere Seiten anzulegen, zwischen denen der User navigieren kann. Das Windows 8 Framework, allen voran WinJS nimmt uns auch hier wieder einen großen Teil der Arbeit ab, unter anderem müssen wir uns nicht um das Erscheinen bzw. das Layout eines “Zurück”-Buttons kümmern, wenn wir zu einer Unterseite navigieren – dies wird ganz automatisch eingefügt (und kann natürlich auch gelöscht werden, wenn wir der Meinung sind, keinen solchen Button zu benötigen).
Wir erweitern die bisher geschriebene App nun so, dass wir mit einem Klick auf unseren Button, der sich bekanntlich auf der “home”-Seite befindet, auf eine “detail”-Seite wechseln. Dazu klicken wir mit der rechten Maustaste auf unseren “pages”-Ordner, wählen “Hinzufügen” > “Neuer Ordner” und nennen diesen “detail”:
Wir klicken nun mit der rechten Maustaste auf den soeben erstellten “detail” Ordner, wählen wieder “Hinzufügen” und “Neues Element”. In der nun erscheinenden Liste wählen wir “Seitensteuerelement” und im Textfeld “Namen” geben wir “detail” ein:
Visual Studio fügt nun in unserem detail-Ordner die Dateien detail.html, detail.css und detail.js hinzu. Diese dreigeteilte Struktur kommt uns bereits bekannt vor, es ist wenig überraschend das selbe Prinzip wie auf unserer “home”-Seite, wenngleich der Code nicht exakt der selbe ist.
Wir wechseln nun in unsere home.js-Datei, löschen die dort befindliche buttonClick-Funktion und ersetzen sie mit folgendem Code:
1: function buttonClick(eventInfo) {
2: WinJS.Navigation.navigate("/pages/detail/detail.html");
3: }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
In Zeile 2 greifen wir auf unsere altbekannte WinJS-library zurück und rufen die Funktion navigate() auf, die uns zur Verfügung gestellt wird, um bei einem Klick auf den Button in home.html zu detail.html zu navigieren. In unsere detail.html schreiben wir noch ein Rezept für einen lecker schmeckenden flockigen Becherkuchen, der ebenso schnell und einfach zu machen ist, wie unsere App. Hier der Quellcode der gesamten detail.html-Datei:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta charset="utf-8" />
<title>detail</title>
<!-- WinJS-Verweise -->
<link href="//Microsoft.WinJS.1.0/css/ui-dark.css" rel="stylesheet" />
<script src="//Microsoft.WinJS.1.0/js/base.js"></script>
<script src="//Microsoft.WinJS.1.0/js/ui.js"></script>
<link href="detail.css" rel="stylesheet" />
<script src="detail.js"></script>
</head>
<body>
<div class="detail fragment">
<header aria-label="Header content" role="banner">
<button class="win-backbutton" aria-label="Back" disabled type="button">
</button>
<h1 class="titlearea win-type-ellipsis">
<span class="pagetitle">Becherkuchen Rezept</span>
<span style="font-size:20px;">von Christine Hudetz</span>
</h1>
</header>
<section aria-label="Main content" role="main">
Um einen flockigen Becherkuchen zaubern zu können benötigt man: Erst einmal
die unersetzlichen Grundzutaten:<p>
<li> 1 Becher Joghurt/Sauerrahm/Schlagobers (letzerer ist am flockigsten)
<li> 1 Becher (ja, den Joghurt/Sauerrahm/Schlagobersbecher) Mehl (am
besten „Universal“)
<li> 1 Becher (noch immer derselbe) Zucker
<li> ½ (!) Becher Öl
<li> 1 Packerl Backpulver
<li> 3 Eier
<p>
Hat man diese flotten Essenzen nun alle (egal in welcher Reihenfolge)
in eine Schüssel zusammenpurzeln lassen, darf man seiner Fantasie freien
Lauf lassen und hinzufügen, wozu man grade Lust und Laune hat.
<p>
Im klassischen Flockkuchen befindet sich (mind.) 1 Becher Kakao (Erfahrene
Flockbäcker schütten den Kakao einfach nach Gefühl in die Schüssel – ein
einziger Becher erscheint alteingesessenen Flockkennern meist etwas banal)
Eine weitere klassische Zutat sind geriebene Nüsse – egal welcher Sorte –
sie geben dem Becherkuchen ein noch flockigeres Geschmacksspektrum.
Für einen wohltuenden Schokolade-Schock empfiehlt sich jedoch die
reine Kakao-Variante.
<p>
Weitere typische Zutaten wären:<br>
<li> ganze Nüsse
<li> Schokoladestücke
<li> Rosinen
<li> Kokosraspeln
<li> Zimt (gibt dem Kuchen einen flockig weihnachtlichen Touch!)
<li> Vanille(zucker)*
<li> usw usf - Der Kreativität der Flockisten sind keine Grenzen gesetzt!
<p>
*Anm.: Eine rein mentale Zutat. Bringt geschmacklich keine merkliche
Veränderung.
<p>
Nachdem man mit der Wahl seiner Zutaten zufrieden geworden ist und die
Schüssel nach Belieben mit flockigen Substanzen bereichert hat, mixt man
das Ganze bis alles gut vermischt harmonisch vor sich her döst.<br>
Währenddessen kann man schon mal den Ofen auf 180° (Ober- und Unterhitze)
einschalten und vorglühen lassen. Dann darf man sich ein Stück Butter
krallen und damit vergnügt die Backform (Gugelhupf, Rehrücken,
Tortenform,...) auskleiden. Als krönenden Abschluss bespreuselt man
die ausgebutterte Form dann noch mit Semmelbröseln – möglichst ohne
bröselfreie Zonen, um potentiellem Festkleben des Kuchens keine Chance
zu geben und ein einwandfreies Loslösen des fertigen Kuchens zu
garantieren.<br>
Ist die Form nun fertig ausgebröselt füllt man sie grazil mit dem
flockig-vermixten Teig.
Wer jetzt noch nicht genug Spaß am Herumflocken hatte, kann noch
Schokoladestückchen in die Backform plumpsen lassen. Oder Schokostreusel,
oder Rosinen, oder Kokosraspeln,...<p>
Danach schiebt man die Form auf mittlerer Schiene in den Backofen und
wartet ab. Solange, bis der Kuchen schön flauschig geworden ist
(ca. 45-50 min. - je nachdem wie lange man den Ofen verheizen hat lassen).
<br>
Hat der Kuchen die perfekte Konsistenz erreicht, holt man ihn aus dem
Backrohr und stülpt ihn aus der Form. Ambitionierte Einbutterer und
Ausstreusler können sich nun sicher über ein einwandfreies Ergebnis
freuen. Faulere Individuen werden mit kleinen Verlusten zu rechnen haben.
<p>
Der fertiggebackene Kuchen kann nun beliebig mit Staubzucker, Streusel
oder (für den Extra-Schoko-Flash) Schokoladeüberguss dekoriert werden.
<p>
Dines flockiger Becherkuchen eignet sich selbstverständlich auch perfekt
für Geburtstags- und Hochzeitstorten – ein wahres Universalrezept also.
<p>
Viel Spaß beim Nachflocken, wünscht Dine.
</section>
</div>
</body>
</html>
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Wenn wir nun mit dem Shortcut F5 die App starten und auf den Button klicken, sollten wir auf unsere detail.html Seite gelangen, auf der sich nun unser Rezept befindet. Automatisch angelegt wurde neben der Überschrift auch ein “Zurück”-Button.
Auffällig ist hierbei, dass – je nach Auflösung – der Text abgeschnitten ist und ein langweiliger schwarzer Hintergrund sowie ein einfacher Button niemanden vom Hocker haut. In einem letzten Schritt wagen wir uns jetzt an das Design, um unserer App ein bisschen Leben einzuhauchen.
Pimp your site with CSS
Wir wollen in diesem Abschnitt unserer App ein Hintergrundbild verpassen sowie den Button auf der home-Seite durch ein Vorschaubild mit Text ersetzen. Kümmern wir uns zunächst um das Hintergrundbild. In diesem Beispiel soll für jede Seite das gleiche Bild verwendet werden, wir müssen daher unsere default.css Datei anpassen, die sich im Ordner css befindet. Hier fügen wir ganz am Ende des default.css-files folgenden Eintrag hinzu:
1: body {
2: background-image:url(/images/background.png);
3: }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Damit wird für den <body>-Tag das Hintergrundbild background.png definiert, das im Ordner images liegt. Nur: Noch liegt im Ordner images kein solches Bild. Wenn wir einen Blick in images werfen, werden wir dort einige Bilder vorfinden, es handelt sich dabei um verschiedene Logos, die wir uns ebenfalls noch ansehen werden. Zuvor aber suchen wir uns ein nettes Bild mit ausreichend guter Auflösung und ziehen dieses einfach mit gedrückter Maustaste in unseren image-Ordner:
Wenn wir die App starten sollte nun bereits unser Hintergrundbild auf allen Seiten angezeigt werden. Passen wir nun im nächsten Schritt auch den Button an. Dazu wechseln wir in unsere home.html-Datei und ersetzen den Button, den wir angelegt haben mit folgendem Code:
<div id="beispielbutton1" class="ManipulationElement" style="-ms-grid-column: 2">
<img alt="Cliff" src="/images/becherkuchen.jpg" style="width:250px;height:250px;"/>
<div class="overlay">
<h2>Becherkuchen</h2>
<p>von Christine Hudetz</p>
</div>
</div>
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Hier passiert nicht viel Magisches: Wir definieren lediglich einen <div>-Bereich, weisen diesem die ID zu, die zuvor unser Button hatte und definieren eine class-property die wir sogleich benötigen, um das Element in CSS stylen zu können. Innerhalb des <div> liegt ein Bild, das in der src auf ein Bild eines Becherkuchens verweist, das wir ebenso wie das Hintergrundbild in den images-Ordner ziehen müssen. Zuletzt folgt ein weiterer <div>-Tag, in dem Text definiert wird, der später halbtransparent am Bild erscheinen soll.
Wechseln wir nun in die home.css Datei und fügen folgenden Code am Ende hinzu:
.ManipulationElement {
position: relative;
display: -ms-grid;
-ms-grid-columns: 1fr;
-ms-grid-rows: 1fr;
height: 250px;
width: 250px;
top: 50px;
}
.ManipulationElement .overlay
{
position: relative;
-ms-grid-row-align: end;
background-color: rgba(0,0,0,0.65);
height: 50px;
padding: 15px 15px;
overflow: hidden;
-ms-grid-column: 1;
}
.ManipulationElement .overlay h2,
.ManipulationElement .overlay p
{
color: rgba(255, 255, 255, 0.8);
margin: 0px;
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Hier wird im wesentlichen die Klasse “ManipulationElement” definiert, die unserem <div> in der home.html bestimmte Styles hinzufügt. Wenn wir nun die App starten, sieht die App – natürlich abhängig von den verwendeten Bildern – etwa wie folgt aus:
Im letzten Schritt soll nun der Text auf der detail.html-Seite, der abgeschnitten ist, sichtbar gemacht werden. Dazu verwenden wir eine schnelle, einfache (und unsaubere) Lösung und ersetzen in Zeile 17 den Code
<div class="detail fragment">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
durch
<div class="detail fragment" style="overflow:scroll;">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Dadurch werden der Seite einfach Scrollbars hinzugefügt.
Wenn wir nun eine Rezeptesammlung mit vielen Rezepten bauen wollen, freut es viele sicher zu lesen, dass es schon fertige Vorlagen gibt, mit denen Apps im Stil einer Grid – so wie wir sie jetzt händisch Stück für Stück gebaut haben – schnell erstellt werden können. Wir klicken dazu im Menü oben auf “Datei” > “Neu” > “Projekt” und wählen “Raster-App” aus. Wenn wir diese App mit F5 starten, sieht sie so aus:
Die grauen Quadrate sind Bilder, die im Ordner images liegen und können natürlich nun im Fall einer Rezepte-App einfach durch eigene Bilder von Speisen und Kuchen ersetzt werden. Alle Daten der App werden übrigens im Ordner js im file data.js definiert.
Zuletzt passen wir noch die Logos an, damit auch unser SplashScreen hübscher wird. Wenn wir auf das Logo splashscreen.png doppelklicken, öffnet sich der in Visual Studio integrierte Grafik-Editor. Hier können einfache Änderungen an der Bildern vorgenommen werden. Mit etwas Motivation lässt sich schnell ein Kuchen-Icon basteln, das ganz im Stil der Standard-Win8-Tiles schlicht und weiß gehalten sein soll.
Die Farbe des SplashScreens lässt sich mit einem Doppelklick auf package.appxmanifest in der Zeile “Hintergrundfarbe” ändern.
Das für den SplashScreen erstellt Logo, können wir nun auch für die anderen Logos verwenden.
Die weiteren Schritte
Wenn wir eine App erstellt haben, möchten wir diese in der Regel auch einem breiten Publikum vorstellen und sie im Windows Store veröffentlichen. Um dies zu bewerkstelligen, navigiere man zunächst auf die Registrierungs-Seite des Windows Dev-Centers. Nach einem klick auf “Jetzt registrieren” können sich Besitzer eines Windows-Accounts einloggen oder neue User mit einem Klick auf “Weiter” in der linken Spalte registrieren. Für die Registrierung ist neben der Angaben von persönlichen Daten auch eine Kreditkarte erforderlich. Für Studenten ist (im Rahmen des DreamSpark Programms) die Mitgliedschaft kostenlos.
Ist der Account angelegt und die App fertig, steht der Veröffentlichung nichts mehr im Wege. In diesem Blogeintragfindet sich eine Schritt-für-Schritt-Anleitung, um die App in den Store zu bekommen und typische Fehler zu vermeiden.
Ressourcen
Windows Dev-Camp: Entwickeln von Windows Store Apps
Windows 8 Frameworks
Datenschutzrichtlinien für Windows Store Apps
Von
Toni Pohl (Gastblogger)
7. March 2013 07:05
Ganz frisch eingetroffen sind die “Office Developer Tools for Visual Studio 2012” so schreibt S. Somasegar, Corporate Vice President of the Developer Division at Microsoft, in seinem Blog: Now Available: Office Developer Tools for Visual Studio 2012.
[More]
Von
Philipp Wintersberger (Gastblogger)
1. March 2013 17:50
Nachem ich bereits einen kleinen Einblick in das Thema Gestenerkennung gegeben habe, folgt nun die Theorie. In Teil 1 haben wir künstliche Intelligenz bereits folgend definiert: Als die Fähigkeit, neue und bisher unbekannte Herausforderungen erfolgreich zu meistern...
[More]
Von
Rina Ahmed
19. February 2013 15:59
Mit der Einführung von Windows 8 haben Web-Entwickler erstmals die Möglichkeit, Apps für den Windows Store mit den ihnen bekannten Webtechnologien HTML/CSS und JavaScript zu entwickeln. Hierbei muss man sagen, dass Microsoft diese Technologien nicht einfach nur halbherzig unterstützt, sondern wie in Abbildung 1 ersichtlich ist, diese eine gleichwertige Alternative zu den bereits bekannten .Net Sprachen darstellen. Abb. 1 Das heißt also, dass ich eine Windows Store App entwickeln kann, indem ich meine Businesslogik in JavaScript schreibe und mein Frontend wie gewohnt in HTML und mit CSS baue. Der große Vorteil hier ist aber, dass ich mittels der WinRT APIs auch Zugang zu gerätespezifischen Features habe, wie zum Beispiel Geolocation. Für Webentwickler ist das eine ganz spannende Sache, weil sich neue Möglichkeiten für tolle Apps ergeben. Den Beweis, dass man super Windows Store Apps in JavaScript schreiben kann, liefert gleich Microsoft selbst. Die Standard Windows 8 Apps, die auf jedem Windows 8 Gerät bereits von Haus aus installiert sind, wurden gänzlich oder teilweise in JavaScript geschrieben. Wenn man sich diese Apps, wie zum Beispiel Wetter, Finanzen und Nachrichten anschaut, so sehen wir, dass diese Apps nicht nur schön aussehen, sondern vollwertig in die Windows 8 User Experience integriert sind. Microsoft hat damit einen wesentlichen Schritt in Richtung Unterstützung von Standards getan und führt mit gutem Beispiel. Um nun tolle Windows 8 Apps mittels JavaScript zu schreiben, wird von Microsoft die Windows Library for JavaScript (WinJS) bereitgestellt. Diese Library bietet dem Entwickler APIs, um einerseits das Look and Feel von Windows 8 Apps zu gewährleisten, andererseits können viele spezifische Merkmale von Windows Store Apps, wie Touch Support, Application Management, Charms und Navigation leicht implementiert werden. Webentwickler, die auf offene Standards besonders großen Wert legen, denken sich vielleicht nun, warum sie Windows Store Apps schreiben sollten, wenn sie erst recht wieder die proprietäre Library von Microsoft verwenden sollen. Dazu muss man sagen, dass es nicht verpflichtend ist, diese Library zu verwenden. Man kann sehr wohl, alles selbst schreiben. Aber um in den Windows Store zu kommen, ist es erforderlich gewisse Windows 8 Funktionalitäten zu unterstützen und es kann mitunter viel Code sein, wenn man alles selbst schreiben will. Kurz gesagt, die WinJS Library vereinfacht es, hochqualitative Apps mit der Windows 8 User Experience zu schreiben. Es gibt auch einige wesentliche Gründe, warum Web-Entwickler sich Windows Store Apps genauer ansehen sollten. Bekanntheit Bis auf die bereits erwähnte WinRT und WinJS APIs unterstützt Microsoft den Standard in HTML5, CSS3 und JavaScript. Alles, was ihr über diese Technologien gelernt haben, könnt ihr für Windows Store Apps verwenden. Das Schreiben von Apps für den Windows Store fühlt sich so an, als ob ihr auch für das Web wie bisher entwickelt habt. Natürlich muss man etwas dazulernen, aber die Menge hält sich in Grenzen. Man kann ziemlich schnell beginnen an einer App zu schreiben. Spannend ist besonders, dass Webentwickler nun auch die Möglichkeit haben auf gerätespezifische Merkmale wie Geolocation, Accelerometer durch die WinRT APIs zuzugreifen, was früher nur Desktopentwicklern vorbehalten war. Portabilität Der klare Vorteil bei der Verwendung von Webtechnologien wie HTML und JavaScript ist natürlich, dass diese über verschiedene Plattformen hinweg laufen. Dass Microsoft jetzt eine Unterstützung für HTML5 und Javascript bietet, lässt den Windows Store als eine weitere Option für Entwickler erscheinen, die Apps für mehrere Plattformen schreiben wollen. Klar, man soll sich bei den verschiedenen Plattformen an die jeweiligen Designrichtlinien halten. Aber wenn man bei den Windows Store Apps die WinJS und WinRT API calls entfernt, so kann man sicher sein, dass der restliche JavaScript Code überall problemlos läuft, wo JavaScript unterstützt wird. Microsofts Anstrengungen, offene Standards zu unterstützen, gehen so weit, dass sie Änderungen im Standard, die es zur Zeit des ersten Windows 8 Preview noch nicht gaben, im Nachhinein noch im nächsten Preview eingebaut haben. Das gibt dem Entwickler die Sicherheit, dass sein den Standards entsprechend geschriebener Code auch überall läuft und, dass Microsoft nicht vorhat, Entwickler fest an Windows zu ketten. Reichweite Es steht außer Frage, dass Windows das meist verbreitete Betriebssystem ist. Die Apps, die Webentwickler schreiben, stehen nun zusätzlich allen Benutzern im Windows Store zur Verfügung. Bereits in den ersten zwei Monaten wurden 60 Millionen Windows 8 Lizenzen weltweit verkauft. Hier bildet sich für den Webentwickler eine große Chance, seine Apps mit einer riesigen Benutzergruppe zu teilen und sein Talent zur Schau zu stellen. Natürlich kann das auch eine lukrative Möglichkeit sein, mehr Benutzern die App zum Kauf anzubieten. Wenn ihr bereits mit Webtechnologien gearbeitet habt, so könnt ihr also mit einer kleinen Lernkurve bald eigene App für den Windows Store schreiben. Ich hoffe, dass euch die obigen Gründe, Windows Store Apps schmackhaft gemacht haben und probiert mal selbst aus, wie ihr ganz ohne .Net supertolle Apps für Windows 8 entwickeln könnt. Ressourcen: Windows 8 Store Apps Why Front-End Developers Should Build Apps for Windows 8 Building the Bing apps for Windows 8
Von
Rina Ahmed
10. February 2013 11:26
Wenn man eine Windows 8 App schreibt und persistente Daten zum Speichern hat, stellt sich über kurz oder lang die Frage, welche Backend-Lösung man für die Daten verwenden will. Windows Azure Mobile Services bieten hierbei eine einfache Lösung, um eine Datenbank in der Cloud für Windows 8 Apps zu nutzen. In diesem Tutorial will ich anhand einer einfachen Windows 8 App, die Artikel in einer Einkaufsliste speichert, zeigen, wie man auf die Schnelle die Datenbank erstellen und für die App verwenden kann. Folgende Schritte werden wir durchgehen: Vorbereitung Einrichten eines Windows Azure Mobile Services Erstellen einer Tabelle Eine einfache Windows 8 App schreiben Direkter Zugriff auf die Datenbank in Visual Studio Vorbereitung Wir benötigen für unsere App Visual Studio und Windows Azure SDK. Falls ihr es noch nicht installiert habt, könnt ihr hier Visual Studio Express 2012 und Windows Azure SDK herunterladen. Um die Services von Windows Azure in Anspruch zu nehmen, ist auch Windows Azure Konto notwendig. Hier kann man sich für ein 90-Tage gratis Trial anmelden. Jetzt müssen wir die Mobile Services in unserem Azure Account noch aktivieren. Geht auf die Seite https://account.windowsazure.com und loggt euch mit eurer Live Id ein. Ihr klickt dann auf den Punkt Vorschaufeatures. Auf der Seite der Vorschaufeatures aktivieren wir die Mobile Services mittels Try it now. Einrichten eines Windows Azure Mobile Services Nachdem wir nun die Grundvoraussetzungen erfüllt haben, können wir mit unserer App beginnen. Wir wollen eine einfache Einkaufsliste entwickeln, in der wir Artikel eingeben können, die dann in einer Datenbank mittels Windows Azure Mobile Services gespeichert werden. So richten wir unser Windows Azure Mobile Service ein: Zuerst müssen wir uns im Windows Azure Management Portal unter http://manage.windowsazure.com mit der Live Id anmelden. In der unteren Leiste klickt Ihr auf Neu. Danach wählt Ihr den Punkt Mobiler Service und klickt auf Erstellen. In dem Dialogfeld müsst Ihr einen Namen für das Mobile Service auswählen, der Teil der URL sein wird. Das heißt, wenn der Name bereits vergeben ist, müsst Ihr einen ähnlichen Namen wählen. Danach wählt ihr Eine neue SQL-Datenbankinstanz erstellen und North Europe als Region und klickt auf den Pfeil unten. Im zweiten Schritt wählt ihr unter Server den Punkt Neuer SQL-Datenbankserver und gebt ein Username und Passwort an. Wichtig: merkt euch den Username und das Passwort, da ihr denselben Datenbankserver für weitere Mobile Services verwenden könnt. Falls ihr bereits einen Datenbankserver erstellt habt, dann wählt ihr unter Server diesen aus und gebt eure Anmelde-Daten für den Server an. Ihr habt jetzt ein Mobile Service erstellt, dass ihr ansprechen könnt. Bevor wir uns der App widmen, müssen wir noch eine Tabelle in unserer Datenbank erstellen. Erstellen einer Tabelle In unserem Management Portal gehen wir auf Mobile Services und wählen das gerade von uns erstellte Mobile Service aus. Dort klicken wir auf Daten in der oberen Leiste. Danach gehen wir auf Eine Tabelle hinzufügen. Da wir in unserer Einkaufsliste Artikel speichern wollen, benötigen wir eine Tabelle namens Artikel. Nun haben wir in unserem Mobile Service die Tabelle für unsere Artikel Objekte erstellt. Wenn wir auf unsere Tabelle jetzt klicken und auf Spalten gehen, sehen wir, dass diese Tabelle bereits eine Spalte namens Id besitzt. Eine einfache Windows 8 App schreiben Zunächst erstellen wir uns ein neues Projekt in Visual Studio unter Datei/Neu… . Wir wählen die Kategorie Windows Store unter C# nehmen die Leere App und geben MeineEinkaufsliste als Namen an. Links im Solution Explorer klicken wir mit rechter Maustaste auf References und dann auf Add reference. Unter Extensions klicken wir Windows Azure Mobile Services Managed Client an (Das setzt voraus, dass wir in der Vorbereitungsphase Windows Azure SDK installiert haben). Im Solution Explorer auf der rechten Seite können wir alle Dateien in unserem Projekt sehen. Wir öffnen durch Doppelklick die Dateien App.xaml.cs und MainPage.xaml.cs und fügen in beiden Dateien oben folgendes Statement ein: using Microsoft.WindowsAzure.MobileServices;
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
In App.xaml.cs fügen wir folgenden Code gleich über dem Konstruktor der Klasse App hinzu:
public static MobileServiceClient MobileService = new MobileServiceClient(
"https://meineeinkaufsliste.azure-mobile.net/",
"jdJuIxpihCodEilnMsCVIFORiMHuXm99"
);
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Wir stellen hier eine Instanz für den MobileServiceClient bereit, wobei wir dem Konstruktor, die URL des Mobile Services und den Anwendungsschlüssel als Parameter übergeben. Diese zwei Werte müsst Ihr gemäß eurer App ersetzen.
Die Werte findet Ihr, wenn Ihr im Azure Management Portal unter Mobile Services auf euer Mobile Service geht und oben Dashboard wählt. In der rechten Spalte befindet sich die URL des Mobile Services und in der unteren Leiste im Punkt Schlüssel Verwalten könnt ihr den Anwendungsschlüssel rauskopieren.
In der Datei MainPage.xaml.cs schreiben wir eine Klasse für unsere Artikel Objekte. Ihr könnt den Code direkt oberhalb der MainPage Klasse einfügen.
public class Artikel
{
public int Id { get; set; }
[DataMember(Name = "bezeichnung")]
public string Bezeichnung { get; set; }
[DataMember(Name = "gekauft")]
public bool Gekauft { get; set; }
}
Und dann fügen wir noch folgendes Statement oben im using Block hinzu:
using System.Runtime.Serialization;
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Wir haben nun eine Klasse Artikel geschrieben, die eine Variable Bezeichnung für den Namen des Artikels und eine Variable Gekauft besitzt, um anzugeben, ob der Artikel noch ausständig ist oder bereits gekauft. Durch [DataMember(Name=”bezeichnung”)] haben wir sichergestellt, dass die Klassenvariable Bezeichnung einer Spalte in der Tabelle Artikel entspricht. Unsere Tabelle Artikel in unserem Mobile Service besitzt ein Dynamisches Schema. Wenn wir ein Artikel-Objekt an das Mobile Service schicken, werden automatisch die Spalten generiert.
In der Klasse MainPage fügen wir folgende Variablen oberhalb dem MainPage()-Konstruktor:
private MobileServiceCollectionView<Artikel> artikel;
private IMobileServiceTable<Artikel> artikelTable =
App.MobileService.GetTable<Artikel>();
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }Hier stellen wir eine Instanz der Tabelle aus unserem MobileService als artikelTable bereit und definieren eine Collection für unsere Artikel Objekte, die wir aus der Tabelle einlesen wollen.
Dann fügen wir noch folgende Methoden in der Klasse hinzu.
private async void InsertArtikel(Artikel art)
{
await artikelTable.InsertAsync(art);
artikel.Add(art);
}
private async void UpdateCheckedArtikel(Artikel art)
{
await artikelTable.UpdateAsync(art);
artikel.Remove(art);
}
private void RefreshArtikel()
{
artikel = artikelTable
.Where(art => art.Gekauft == false)
.ToCollectionView();
//Artikelliste.ItemsSource = artikel;
}
InsertArtikel und UpdateCheckedArtikel fügen das als Parameter übergebene Artikel Objekt in die Tabelle in unserem MobileService ein bzw ändern die Daten in der Update Methode. In der RefreshArtikel Methode lesen wir alle Artikel, die noch nicht gekauft wurden, aus der Tabelle in unsere Collection artikel. Wir wollen, dass diese Methode aufgerufen wird, sobald der User auf die Seite kommt, daher machen wir den Methodenaufruf in der OnNavigatedTo-Methode, die in der Vorlage bereits bereitgestellt wird.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
RefreshArtikel();
}
Jetzt fügen wir noch zwei EventHandler-Methoden in der Klasse hinzu.
private void SaveButton_Click(object sender, RoutedEventArgs e)
{
//Artikel art = new Artikel
//{ Bezeichnung = Artikelbezeichnung.Text};
//InsertArtikel(art);
}
private void CheckBoxComplete_Checked(object sender, RoutedEventArgs e)
{
CheckBox cb = (CheckBox)sender;
Artikel art = cb.DataContext as Artikel;
UpdateCheckedArtikel(art);
}
In der SaveButton_Click-Methode behandeln wir das Ereignis, in dem ein Benutzer auf den Speichern Button klickt, nachdem er einen neuen Artikel eingegeben hat. Wir erstellen ein neues Artikel-Objekt und rufen die InsertArtikel-Methode zum Einfügen in die Tabelle auf. Da wir das User Interface noch nicht erstellt haben, kommentieren wir den Code aus, nachdem wir die Controls in der MainPage.xaml definiert haben.
In der CheckBoxComplete_Checked-Methode behandeln wir das Ereignis, in dem ein Benutzer die Checkbox anklickt, um anzudeuten, dass der Artikel gekauft wurde. Hier rufen wir die UpdateCheckedArtikel-Methode auf.
Wir gehen nun zu der Datei MainPage.xaml und ersetzen das Grid-Element mit folgendem Code:
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"/>
<ColumnDefinition Width="400"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="120"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Grid.Column="1" Text="Einkaufsliste" Style="{StaticResource PageHeaderTextStyle}" Margin="0"/>
<StackPanel Grid.Column="1" Grid.Row="2" Margin="0,50,0,0">
<TextBlock Text="Artikelbezeichnung:" Style="{StaticResource BasicTextStyle}"/>
<TextBox x:Name="Artikelbezeichnung" Width="250" Height="30" HorizontalAlignment="Left"/>
<Button Content="Speichern" Margin="0,10,0,0" Click="SaveButton_Click" />
</StackPanel>
<StackPanel Grid.Column="2" Grid.Row="2">
<TextBlock Text="Meine Artikel:" Margin="0,0,0,20" Style="{StaticResource BasicTextStyle}"/>
<ListView x:Name="Artikelliste">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<CheckBox Name="CBgekauft" IsChecked="{Binding Gekauft, Mode=TwoWay}"
Checked="CheckBoxComplete_Checked" Content="{Binding Bezeichnung}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackPanel>
</Grid>
Jetzt fehlt noch das Auskommentieren des Codes in der SaveButton_Click-Methode in MainPage.xaml.cs, sowie das Auskommentieren der letzten Zeile (Artikelliste.ItemsSource = artikel; ) in der RefreshArtikel-Methode.
Als letzten Punkt wollen wir noch den Look der App auf das helle Farbschema ändern. Dazu gehen wir in die App.xaml Datei und fügen im Application-Element das Attribut RequestedTheme mit dem Wert Light ein. Das Ganze sieht dann so aus:
<Application
x:Class="MeineEinkaufsliste.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MeineEinkaufsliste"
RequestedTheme="Light">
Nun können wir unsere App ausprobieren. Wenn ihr in Visual Studio F5 drückt, dann wird die App kompiliert und gestartet. Ihr könnt im linken Teil Artikelbezeichnungen eingeben, die in die Datenbank mittels Mobile Service eingefügt werden und im rechten Teil werden die aus der Datenbank ausgelesenen Artikel angezeigt. Bei der Abfrage nach der Artikel werden nur jene angezeigt, die den Wert false in der Gekauft Spalte haben. Der Wert false wird dann auf der Seite mit einer leeren Checkbox dargestellt.
Direkter Zugriff auf die Datenbank in Visual Studio
Wir haben bereits ein Mobile Service mit einer Datenbankinstanz eingerichtet und eine Tabelle erstellt. Weiters haben wir das aus den Eingabewerten erstellte Artikel Objekt in die Tabelle eingefügt und aus der Tabelle anhand der Spalte Gekauft selektiert ausgelesen. Wir haben also eine funktionierende Backend-Lösung, ohne eine einzige Zeile SQL geschrieben zu haben!
Es kann aber Fälle geben, in denen es praktischer ist, die Datenmanipulation direkt mit SQL zu erledigen als über eine grafische Oberfläche. Wenn wir beispielsweise eine weitere Spalte namens Menge in unserer Tabelle hinzufügen wollen, genügt es in unserer Klasse Artikel in MainPage.xaml.cs ein weitere Klassenvariable (als DataMember deklariert) namens Menge hinzuzufügen und im Interface Felder für das Einlesen und Ausgeben der neuen Information vorzusehen. Wegen des dynamischen Schema wird beim nächsten Einfügen eines Artikels mit Mengenangabe automatisch eine weitere Spalte in der Tabelle hinzugefügt. Alle unsere bisherigen Daten werden allerdings Null-Werte in der neuen Spalte haben. Wenn wir sinnvollere Werte für die Spalte Menge in den bisherigen Artikel Datensätzen haben wollen, ist es am schnellsten, dies mit einem UPDATE Statement in SQL zu realisieren. Dieses Szenario wollen wir nun durchspielen, damit wir sehen können, wie wir direkt auf die Datenbank unseres Azure Mobile Services zugreifen und SQL Code ausführen können.
Als erstes ändern wir die Artikelklasse in MainPage.xaml.cs und fügen eine weitere Klassenvariable Menge ein, sodass unsere Artikelklasse so aussieht:
public class Artikel
{
public int Id { get; set; }
[DataMember(Name = "bezeichnung")]
public string Bezeichnung { get; set; }
[DataMember(Name = "gekauft")]
public bool Gekauft { get; set; }
[DataMember(Name = "menge")]
public string Menge { get; set; }
}
Danach ändern wir die Methode für das Event des Buttonklicks beim Speichern. Wir wollen bei der unserem neuen Artikel Objekt, die vom Benutzer angegebene Menge miteinberücksichtigen. Unsere SaveButton_Click Methode sieht daher so aus:
private void SaveButton_Click(object sender, RoutedEventArgs e)
{
Artikel art = new Artikel
{ Bezeichnung = Artikelbezeichnung.Text,
Menge = Menge.Text};
InsertArtikel(art);
}
Nun fügen wir in der MainPage.xaml unmittelbar über die Definition für den Speichern Button die Zeilen, um ein Eingabefeld für die Artikelmenge zu erstellen.
<TextBlock Text="Menge:" Style="{StaticResource BasicTextStyle}" Margin="0,15,0,0"/>
<TextBox x:Name="Menge" Width="50" Height="30" HorizontalAlignment="Left"/>
Gleich nach dem CheckBox Element in unserer ListView namens Artikelliste fügen wir diese Zeile ein:
<TextBlock Name="Artikelmenge" Text="{Binding Menge}" Margin="27,0,0,5"/>
Wenn wir jetzt unsere App starten (F5), so sehen wir dass wir jetzt Artikel mit Mengenangabe eingeben können und für alle Artikel wird die Mengenangabe anzeigt. Wenn wir jetzt auf unser Management Portal gehen und in unserer Tabelle Artikel (unter dem erstellten Mobile Services auf Daten klicken) den Tab Spalten in der oberen Leiste wählen, so sehen wir dass unsere Tabelle jetzt auch eine Spalte Menge besitzt.
In unserer App sehen wir auch die neue Information der Artikelmenge.
Bevor wir versuchen, auf die Datenbank direkt in Visual Studio zugreifen zu können, müssen wir noch sicherstellen, dass unsere IP als erlaubte Zugriffsquelle im Azure Management Portal gelistet ist. Zunächst wählt ihr unter Datenbanken, die DB Instanz eures Mobile Services. Dort findet ihr in der rechten Spalte den Link Zulässige IP-Adressen verwalten.
Hier habt ihr nun zwei Möglichkeiten eure IP Adresse einzugeben. Entweder ihr übernimmt die vorgeschlagene IP unter Aktuelle Client-IP-Adresse, indem ihr auf den Pfeil daneben (rote Markierung) klickt oder ihr gebt die IP bzw den IP Adressenbereich selbst ein (orange Markierung). Ich habe im Screenshot einige IP Adressen vom Screenshot entfernt, daher seht ihr dort einige leere Felder.
Damit eure Eingabe übernommen wird, müsst ihr noch in der unteren Leiste auf Speichern klicken.
In Visual Studio findet ihr am linken Rand den SQL Server Object Explorer. Dort klickt ihr auf das Icon, um eine neue SQL Instanz hinzuzufügen.
In dem Dialogfeld gebt ihr nun den Server-Namen und die Login-Daten für eure DB ein, die ihr beim Einrichten des Mobile Services im dritten Schritt eingegeben habt. Den Server-Namen findet ihr direkt nach dem Punkt Zuständige IP-Adressen verwalten, den ihr im vorigen Schritt dieses Tutorials gesehen habt.
Jetzt wo eure Datenbank hinzugefügt ist, klicken wir im SQL Server Object Explorer auf das Icon für eine neue Query.
Und dann wählen wir in der SQL Datei in der oberen Leiste im Drop Down Feld unsere Datenbankinstanz aus.
Nun sind wir bereit im Fenster SQL Code zu schreiben und auszuführen. Beginnen wir mit einem einfachem SELECT Statement. Gebt im SQL Fenster den grün markierten Befehl ein. Vor dem Tabellennamen haben wir unseren Schema-Namen, der Name des Mobile Services in unserem Fall ein. Mit Strg + Shift + E können wir den Befehl ausführen oder wir klicken auf den rot markierten Pfeil. Darunter sehen wir im Ergebnisfeld unsere Ergebnisdaten, in diesem Falle alle Rows.
Nun wollen wir alle Artikel, die in der Spalte Menge einen Nullwert besitzen auf einen sinnvollen Wert, beispielsweise 1, updaten. Dazu schreiben wir folgendes UPDATE Statement in das SQL Fenster und führen es wieder aus.
UPDATE MeineEinkaufsliste.ArtikelSET menge = '1'WHERE menge IS NULLGO
Wenn wir jetzt wieder das obige SELECT Statement aus dem vorigen Schritt ausführen, so bekommen wir das erwartete Ergebnis.
Wir haben nun erfolgreich eine Windows 8 App geschrieben, die eine Backend in der Cloud hat. Wie ihr gesehen habt, ging das ganze sehr schnell und unkompliziert. Wir haben auch gesehen, wie wir die Datenbank direkt ansprechen können und unsere Daten mittels T-SQL manipulieren können. In einem späteren Teil werden wir uns anschauen, wie wir Daten validieren können, bevor wir diese in die Tabelle einfügen.
Hier sind noch alle Ressourcen für dieses Tutorial aufgelistet.
Ressourcen:
Visual Studio Express 2012
Windows Azure SDK
Windows Azure kostenlos testen
Windows Azure Mobile Services
Windows Store Apps
Getting Started with Data in Mobile Services
Von
Philipp Wintersberger (Gastblogger)
17. January 2013 21:00
Den Anwender Symbole am Touchsreen zeichnen lassen um bestimmte Aktionen auszulösen? Das Handy das von selbst erkennt, ob sein Benutzer gerade im Zug oder doch zuhause sitzt? Bei der täglichen Jogging-Session automatisch Anrufe unterdrücken? Ein Bowling Spiel bei dem das Smartphone die Rolle der Kugel einnimmt?
Apps mit derartigen (gern gesehenen) Features haben nicht nur für Developer seinen Reiz, sie wirken ausgereifter und verkaufen sich meist auch besser – nicht nur weil es „cool“ ist, sondern weil ein erweitertes Set an Inputmodalitäten auch dafür sorgt dass sich Benutzerinteraktionen natürlich anfühlen und der ohnehin schon kleine Screen nicht mit überflüssigen Buttons belastet wird. Schließlich werden die Geräte mit einer Vielzahl an Sensoren ausgeliefert - daher sollte man sie wenn möglich auch nutzen! [More]
Von
Toni Pohl (Gastblogger)
9. January 2013 07:15
In Teil 1 und Teil 2 ging es um die Basis und um die Funktionsweise von OfficeApps und SharePointApps. Wenn diese erfüllt sind, geht es schon los und wir sehen uns hier in Teil 3 an, wie eine Office-App aufgebaut ist und wie sie funktioniert. Dazu erstellen wir ein kleines Beispiel mit Visual Studio 2012.
[More]
Von
Toni Pohl (Gastblogger)
7. January 2013 07:15
In Teil 1 habe ich über das Grundgerüst von OfficeApps geschrieben, über die Anatomie einer App und wie sie gehostet werden kann. Grundsätzlich gelten dieselben Regeln für OfficeApps und SharePointApps. Aufgrund der SharePoint 2013 Developmentplattform gibt es aber natürlich einige Besonderheiten für SharePointApps. Auf einige davon möchte ich in diesem Artikel eingehen.
[More]
Von
Toni Pohl (Gastblogger)
6. January 2013 07:15
Mit Microsoft Office 2013 und SharePoint Server 2013 gibt es eine neue Welt von “Apps”. Ein neues Applikationsmodell ermöglicht es Apps für Office und SharePoint zu entwickeln, die auf Webstandards und Services setzen. Apps werden nun über Webdienste eingebunden und in SharePoint, in Windows Azure oder bei einem Provider gehostet – sie laufen nicht mehr IN der Applikation, sondern sind gänzlich davon losgelöst.
[More]
Von
Toni Pohl (Gastblogger)
18. December 2012 19:36
Zu Weihnachten darf sich jeder etwas wünschen! Für codefest.at haben wir von atwork eine Windows 8 Reader App spendiert bekommen. Damit können Windows-Developer am Tablet-Computer bequem die neuesten Artikel in attraktiver Aufmachung durchschmökern! Und damit es mit codefest.at nicht so einsam bleibt, wurde auch noch der deutschsprachige DotNet German Bloggers Feed integriert. Volle .net Development-Power mit viel Know How in einer App!
[More]