Laden...

Forenbeiträge von Ares Ingesamt 167 Beiträge

21.05.2014 - 08:20 Uhr

Hallo,

ich habe im Netz ein Beispielprojekt gefunden bei dem ich eine Stelle im Code nicht verstehe. Der Autor bzw. der Seitenbetreiber antwortet nicht, deshalb würde ich gerne mal in die Runde fragen ob folgender async/await Code Sinn macht:


public async Task LoadDataAsync() {
    State = LoadingState.Loading;

    await InitConnectionAsync();
    await DownloadDataAsync();

    State = LoadingState.Complete;
}

private async Task InitConnectionAsync() {
    await Task.Run(async () => {
        MachWas();
        await Irgendwas();
        Nochwas();
    });
}

private async Task DownloadDataAsync() {
    await Task.Run(() => {
        ...
    });
}

Die Funktion von LoadDataAsync() ist klar und ich denke auch Korrekt. Aber welchen Sinn hat die Verwendung von await Task.Run(...)?

Wäre es nicht möglich/besser/gleichwertig den gestarteten Task direkt zurück zu liefern?


private Task InitConnectionAsync() {
    return Task.Run(async () => {
        MachWas();
        await Irgendwas();
        Nochwas();
    });
}

private Task DownloadDataAsync() {
    return Task.Run(() => {
        ...
    });
}

Ist es egal welche Form man verwendet? Gibt es bei der Verwendung von await Task.Run(...) irgendwelche Vorteile? Oder ist das Beispiel einfach falsch?

Vielen Dank für eure Einschätzung!

06.03.2014 - 17:09 Uhr

Ok, praktischer Weise hat MS heute geantwortet:

Die Zahlungen betreffen immer ganze Monate (das war bislang nicht sicher) und werden ausgezahlt solange min. 200 USD Guthaben vorhanden sind. Bei ausreichend Einkünften also monatlich wobei die Auszahlung mit einem Monat Verzögerung erfolgt. Die Zahlung die ich im Februar erhalten habe betrifft also den Dezember. MS hat angemerkt dies zukünftig in den Berichten zu vermerken.

Rechnungen können an folgende Adresse gerichtet werden:

Microsoft Corporation
One Microsoft Way
Redmond, WA 98052-6399
USA

Darüber das eine Rechnung verschickt werden soll war MS im übrigen überhaupt nicht verwundert 😃

06.03.2014 - 10:57 Uhr

Hallo herbivore,

keine Sorge, ich weit davon entfernt wegen irgendetwas in die Luft zu gehen. Ich denke eigentlich, dass ich bei allen Antworten sachlich geblieben bin. Wenn es mal eine Spitze gab sollte spätestens beim darauf folgenden Smily klar sein, dass das Ganze mit Humor gemeint ist.

Natürlich habe ich mich mit der Frage zu erst an Microsoft gewendet. Wie es aber nun mal so ist mahlen die Mühlen eines großen Support sehr langsam und so warte ich schon eine Woche auf Antwort. Oftmals kennen die Nutzer die Systeme ohnehin besser als der Support. Daher meine Frage in die Rund hier ob vielleicht jemand bei seiner Nutzung über die von mir gewünschten Angaben gestolpert ist.

Das war z.B. bei iOS nicht anders: Auf eine vernünftige Antwort von Apple kann man lange warten, ein paar alte Hasen wussten aber sofort wo die Angaben versteckt waren.

Natürlich kann es immer sein, dass eine Frage eigentlich gar nicht zielführend ist um ein Problem zu lösen. Sprich es kann sein, dass ein Problem gar kein Problem ist. Dann kann man die eigentlichen Beweggründe ruhig hinterfragen und so z.B. eine Lösung anbieten die der Fragensteller zunächst gar nicht gesehen hat.

Aber spätestens wenn der Fragesteller auf diese Argumente eingeht, diese anerkennt aber klarstellt, dass diese auf sein konkretes Problem nicht zutreffen sollte das doch reichen. Dann macht es doch deutlich mehr Sinn die ursprüngliche Frage zu beantworten als dem Fragesteller weiter zu erklären, dass die eigene Meinung besser ist.

Ich wollte hier auch nicht "nervern". Ich habe aber eine Frage gestellt und finde es daher nur höflich, wenn ich mich mit den gegebenen Antworten auseinandersetzte und darauf wiederum antworte. Man soll ja auch wissen ob die Frage beantwortet wurde oder nicht.

Ich denke aber man kann das ganze auch abkürze:
Wüsste hier jemand, dass die Information über den Leistungszeitraum sich im Dashboard an Stelle XY versteckt hätte er dies Mittlerweile sicherlich verraten (hoffe ich zumindest 😃 Scheinbar ist dem nicht so. Die Frage ist also beantwortet: "Nein, hier weiß niemand wo die Information zu finden ist."

Sollte ich von MS noch eine Antwort bekommen teile ich diese natürlich gerne. Vielleicht hilft Sie ja dann irgendwann noch jemanden weiter.

06.03.2014 - 08:15 Uhr

Dein Steuerberater weiß besser was ich möchte und was ich nicht möchte, was mir egal ist und was nicht als ich selber? Das ist je mal eine interessante Einstellung 😃

bei mir gibt's keine Probleme; auch nicht mit dem Finanzamt (jedenfalls in dieser Angelegenheit).

Bei dir gibt es also in anderen Fragen Probleme mit dem Finanzamt? Das glaube ich nicht und wäre auch komplett unsinnig. Ich habe nämlich in keiner anderen Frage Probleme mit dem Finanzamt... 😉

06.03.2014 - 07:18 Uhr

Ich zitiere mal etwas, da es dir entgangen zu sein scheint

Nein, der Satz ist mir nicht entgangen. Der Satz enthält aber nur die persönliche Meinung von Abt darüber was mir egal sein kann und was nicht. Ich hoffe aber, dass ich nicht zu vermessen bin, wenn ich davon ausgehe dass ich besser weiß was mir egal ist und was nicht 😃

Ich habe doch mehrfach beschrieben warum ich die Information über den Zahlungszeitraum benötige. Einige können die Beweggründe nicht verstehen, was vollkommen in Ordnung ist. Ich denke aber, dass meine Beweggründe (reichlich Erfahrung in ähnlichen Fragen nun in anderen Stores) durchaus ausreichend sind um die simple Frage nach dem Leistungszeitraum zu rechtfertigen.

Statt zu versuchen zu erklären, dass mein Steuerberater, das Finanzamt und ich im Grund alle keine Ahnung haben wäre es doch viel einfacher auf die eigentliche Frage zu antworten 😃

Vielleicht bringt das schon mal etwas mehr Klarheit.

Vielen Dank für den Link. Der Beitrag beschreibt quasi mein Vorgehen bei Apple und Google. Der Autor schreibt übrigens auch Rechnungen, vielleicht ist das also doch kein reine Spinnerei von mir 😃

Wie genau die Rechnungen aussehen und welche Angaben enthalten sein müssen wird aber nicht gesagt. Ich habe für meine Rechnungen eben herausgefunden, dass der Leistungszeitraum enthalten sein muss.

Auf WP geht der Artikel dabei leider nicht ein. Wenn also noch jemand einen Tipp hat wie man beim MS an die Information kommt bin ich weiterhin für jede Hilfe dankbar.

05.03.2014 - 14:46 Uhr

Meine Frage ist schlicht und einfach:
Weiß jemand ob/wie man zu den Payment Reports des WP Dev Centers den zugehörigen Leistungszeitraum ermitteln kann?

Für die Beantwortung der Frage ist es wenig hilfreich:

  • Mein (Un)Verständnis der App Verkäufe zu diskutieren.
  • Zu überlegen wie man das Finanzamt verklagen kann
  • Die fachliche Kompetenz meines Steuerberaters in Frage zu stellen
  • Zu unterstellen ich würde hier rechtliche Beratung suchen

Also lass und doch nicht über unsinnige Dinge reden sondern einfach bei der Frage bleiben 😃

05.03.2014 - 12:29 Uhr

Genau, ich führe einen ewig langen und teuren Rechtsstreit mit dem Finanzamt. Oder gehe ich doch lieber den anderen Weg, suche mir alle relevanten Daten zusammen und erstelle daraus eine korrekte Rechnung... Mal überlegen welcher Weg für mich sinnvoller ist 😛

Ich habe einige Erfahrung in diesem Konkreten Fall mit dem Finanzamt und will weiteren Ärger vermeiden. Deshalb brauche ich die Daten des Leistungszeitraums in jedem Fall.
Warum ich die Daten benötige ist doch aber auch eigentlich vollkommen wurscht.

MS überweist mir an Tag X Geld und ich weiß nicht auf welchen Zeitraum sich diese Zahlung bezieht. Hier haben vielleicht noch andere User Apps im WP Store und kennen daher die zugehörigen Reports und können mir sagen ob ich etwas übersehe oder ob ich die Informationen an anderer Stelle bekomme.

Das Excel ganz unten kriegst Du nicht?

Nein, einen Report mit diesen Daten habe ich nirgends finden können. Im Dashboard gibt es nur den Transaktion Report der die zuvor beschriebenen Daten enthält. Ich nehme an, dass der Screenshot einfach veraltet ist. Allerdings verstehe ich dann noch weniger, warum MS die Informationen einst zur Verfügung gestellt hat und den Report nun scheinbar eingeschrumpft hat.

05.03.2014 - 09:35 Uhr

Es steht der genaue Zeitraum drauf, es steht die genaue Summe drauf und es steht drauf, welche (Umsatz-)Steuer fällig sind.

Das wären die Informationen die ich brauche, aber die sehe ich nirgends:

  • Login im Dev Center -> Dashboard/Reports/Financial summary

Total paid to date
340,00 EUR

Proceeds since last payment
400,00 EUR

Date		Status		Proceeds	Tax withheld	Amount paid	Currency	Transactions
2/14/2014	Paid		340.00 		0.00 		340.00		EUR 		Export

Hier finde ich also nur den Gesamtbetrag und das Datum der Auszahlung. Lade ich den Report herunter erhalte ich eine Excel Tabelle mit zwei Blätter.

Blatt 1:


Financial summary	
	
Reported date	3/4/2014 UTC
	
Criteria	
Start month	February 2014
End month	February 2014

Hier findet sich ebenfalls nur der Monat der Auszahlung. Start- und End Month kann NICHT der Zeitraum der Umsätze sein. Wo sind dann die Umsätze aus Dezember und Januar geblieben? Wie kann eine Zhlung am 14.02. alle Zahlung aus Februar enthalten?

Blatt 2 enthält eine Liste die für jede App und jeden IAP Artikel zeigt in welchem Land welche Mengen verkauft wurden. Als Date ist immer nur 2/14/2014, also das Datum der Auszahlung, angegeben.

Wo finde ich also die Information über welchen Zeitraum sich die Einnahmen erstrecken?

Ich hatte bezüglich dieses Themas bereits sehr lange Diskussionen mit meinem Steuerberater und dem Finanzamt bei der Klärung der iOS Umsätze. Das Ergebnis: Irgendeine Tabelle mit einer Auflistung der Umsetze ist in keinem Fall ein korrekter Beleg den das Finanzamt akzeptiert. Ob das juristisch korrekt ist oder nicht spielt für mich keine Rolle weil ich mich für diese Beträge nicht mit dem Finanzamt streiten werde. Dieses ist mit einer Rechnung die ich Apple/MS stellt zufrieden solange diese korrekt ist und alle Angaben (Adressen, Steuern, etc.) enthält (was bei den Report Tabellen eindeutig nicht der Fall ist). Also stelle eine Rechnung. Dafür bleibt nur die Frage wo ich die Informationen über den Zeitraum her bekomme. Die Reports (s.o) geben nichts entsprechendes her.

05.03.2014 - 07:59 Uhr

aus meiner Sicht brauchst du keine Rechnung schreiben, wenn das die Gegenseite nicht möchte. Richtig ist, zu jeder Buchung braucht man einen Beleg. Der Finanzreport sollte als Beleg für die Zahlung aber grundsätzlich reichen.

Das wäre zu schön, ist aber leider nicht so. Das heißt für die Buchhaltung wird das sicherlich reichen, nicht aber für das Finanzamt. Bei den Abrechnungen von Umsätzen aus dem iOS App Store hatte ich schon einmal dieselben Probleme.

Für die korrekte Verbuchung und Besteuerung muss man einen korrekten Beleg haben. Daraus muss z.B. deutlich und korrekt hervorgehen wie viel Steuern der Rechnungbetrag enthält, bzw. (was für die Store Umsätze gilt) dass Apple/Microsoft die Steuern bereits bezahlt hat.

Ist das nicht der Fall kann das Finanzamt die Steuern einfach noch einmal abziehen. Angenommen man setzt im Store abzüglich Gebühren 100 EUR um. Apple/MS zahlen darauf 20 EUR Steuern und zahlen einem daher 80 EUR aus. Hat man hierfür keinen ordentlichen Beleg geht das Finanzamt davon aus, dass dies ein Unversteuerter Betrag ist und zieht einfach noch einmal Steuern ab.

Es bleibt also bei meinen beiden Fragen:

  1. Weiß jemand wie ich zu den Zahlungen den zugehörigen Zeitraum herausbekomme? Aus den Berichten geht dies meiner Meinung nach nicht hervor.

  2. An wen (Welches Microsoft) ist die Rechnung zu richten?

04.03.2014 - 13:13 Uhr

Hallo,

vielen Dank für deine Antwort, aber leider geht der verlinkte Artikel nicht auf meine Fragen ein. Dort wird zwar im Detail beschrieben wie man an die Finanzreports kommt, über welchen Zeitraum sich die darin gelisteten Umsätze beziehen wird aber nicht gesagt.

Der Verkauf meiner App startete im November, die erste Zahlung habe ich im Februar erhalten. Mit dem Datum der Zahlung (03.02.) kann ich nichts anfangen. Umfasst die Zahlung die Umsätze aus November, Dezember, Januar, allen drei Monaten, etc.?

Eine Adresse für die Rechnungsstellung wird dort leider ebenfalls nicht genannt.

04.03.2014 - 12:48 Uhr

Hallo,

das ist keine Frage speziell zur Programmierung, aber vielleicht gibt es hier ja einige mit entsprechender Erfahrung:

Ende letzten Jahres habe ich meine erste App für Windows Phone veröffentlicht. Seit kurzem ist nun die erste App für Windows 8.1 im Store. Für WP habe ich nun die erste Zahlung von Microsoft erhalten.

Für eine korrekte Buchhaltung benötige ich natürlich für jede Zahlung die ich sende oder (wie in diesem Fall) erhalte eine Rechnung. Bei den Umsetzung aus dem Windows Phone Store habe ich nun zwei Probleme:

Für die Zahlung die ich erhalten haben kann ich mir im Dashboard des Windows Phone Dev Centers einen passenden Report herunterladen. Dieser gibt aber nur an in welchem Land bzw. mit welcher Währung welche Umsätze erzeugt wurden. Es findet sich aber nirgends eine Information darüber, über welchen Zeitraum die Umsätze entstanden sind.

Zudem habe ich nicht herausfinden können, an wen ich die Rechnungen adressieren muss. Ist hier Microsoft Deutschland der Vertragspartner, oder Microsoft USA?

Dasselbe Problem hatte ich bereits mit Apple als ich mit der iOS Entwicklung begonnen habe. Vielleicht weiß ja jemand, wie das Ganze mit Microsoft läuft. Ich bin in jedem Fall für jeden Tipp dankbar!

22.01.2014 - 07:50 Uhr

Niemand eine Idee? Ich komme damit leider immer noch kein Stück weiter. Über die aktuelle (und vermutlich auch zukünftig) gültige Struktur der ListView finde ich keine vernünftigen Auskünfte. Ich bin also weiter für jeden Tipp dankbar.

20.01.2014 - 11:58 Uhr

Hallo,

ich arbeite gerade daran eine Windows Phone 8 App für Windows 8.1 (Store App) umzusetzen. Hierbei scheitere ich bislang kläglich dran das ListView Control an meine Anforderungen anzupassen:

Ziel ist eigentlich "nur" eine gruppierte Liste bei der jede Gruppe einen Header und einen Footer hat. Header, Listenelemente und Footer sollen dabei jeweils die gesamte Breite der Liste einnehmen (siehe Anhang).

Das Problem ist, dass ich Struktur der ListeView nicht durchschaue. Wie diese ist diese also aufgebaut? Wo muss welches Template und welcher Style geändert werden um das gewünschte Resultat zu erzielen?

Grund für die Verwirrung ist, dass der Aufbau der ListeView von Windows 8 zu Windows 8.1. scheinbar stark geändert wurde (unter "ListView and GridView performance improvements"). Styles und Templates die unter Win 8 verwendet wurde können unter Win 8.1 zum Absturz führen.

Die Dokumentation und viele Beispiel beziehen sich aber noch auf Win 8 und berücksichtigen die Änderungen für 8.1. noch nicht. An einer Stelle werden also Schritte empfohlen die in Win 8.1. schlicht keinerlei Effekt haben oder an anderer Stelle ausdrücklich untersagt werden.

Um den Header über die komplette Breite der Liste zu strecken habe ich bislang z.B. nur die Möglichkeit gefunden einen entsprechend angepassten GroupStyle.ContainerStyle anzugeben. In der Doku zu GroupStyle.ContainerStyle wird aber ausdrücklich vor der Verwendung gewarnt, weil dieses Deprecated ist und in Versionen nach Win 8.1. nicht mehr unterstützt werden wird.

Prima, wie ändere ich also das Alignment des Headers ohne den ContainerStyle? Geht das überhaupt, oder bin ich auf den ContainerStyle angewiesen und muss Abstürze in späteren Win Versionen befürchten?

Das die ListView keine Footer die Gruppen unterstützt ist klar. Ich hatte geplant diese durch ein zusätzliches List-Element umzusetzten. Aber dazu bin ich noch nicht gekommen, weil ja noch einmal der Rest der Liste steht...

Ganz allgemein:

  • Was sind die richtigen Styles/Templates um die Liste als Ganzes zu ändern?
  • Was sind die richten Styles/Templates um eine Gruppe zu ändern?
  • Mit welchen Styles/Templates ändere ich die Items?

Kennt jemand eine klare und schlüssige Beschreibung der aktuellen Struktur der ListeView? Aus welchen Teilen ist diese aufgebaut und wie kann man diese anpassen?

08.12.2013 - 11:32 Uhr

Hallo,

das Argument finde ich durchaus einleuchtend. Im Grunde will ich die MessageBox Klasse ja auch gar nicht beeinflussen. Problem ist, dass da sich von einem allgemeinen Button-Style beeinflussen lässt.

Eine Lösung wäre natürlich den Style nicht automatisch auf alle Buttons anzuwenden sondern in jedem Fall einzeln explizit anzuwenden. Die Umstellung wäre aber aber ziemlich aufwändig.

Die Gefahr, dass die MessageBox Klasse irgendwann einmal eine andere Klasse für die die Buttons verwendet statt "Button" ist natürlich da, aber in der Praxis wohl eher gering.

Aber auch ganz unabhängig von dem konkreten Fall mit der MessageBox interessiert mich die Frage, ob man in einem Style für Element X den Style für Unterelemente angeben kann?

Kann man also z.B. in einem Style für ein Grid angeben welcher Style für alles Buttons gelten soll die in diesem Grid enthalten sind?

07.12.2013 - 16:40 Uhr

Hallo,

In einer Windows Phone 8 App verwende ich einen zentralen Style um das Aussehen von allen Buttons in der App zu ändern:


<Style TargetType="Button" BasedOn="..."/>
  ...
</Style>

Dieser Style für die Buttons wird auch wirklich überall in der App verwendet nur an einer Stelle nicht: In einer MessageBox. Hier sollen die Buttons anders aussehen.

Die Frage ist nun, wie ich den Style der Buttons in der MessageBox (nicht die System MessageBox sondern eine Drittkomponente) ändern kann. Ich weiß nur, dass die MessageBox intern Buttons verwendet (sonst würde ja der Style nicht greifen), kann diese aber nicht direkt ansprechen oder ändern.

Ich kann einen Style für die MessageBox-Klasse defieren, aber ich weiß nicht wie ich dort die Buttons ansprechen könnte:


<Style TargetType="ThirdPartyMessagebox" BasedOn="..."/>
   <Setter Property="Background" Value="Blue"/>
   ....
   <Setter Property="ButtonStyle" Value="{StaticResource SomeStyle}"/>
</Style>

Eine Eigenschaft wie ButtonStyle gibt es leider nicht. Kann man irgendwie in einem Style für ThirdPartyMessagebox definieren welcher Style innerhalb dieses Elements für Buttons verwendet werden soll?

21.11.2013 - 10:59 Uhr

Im Grunde geht es hier doch nicht um async sondern allgemein um die Verwendung mehrerer Threads. Also nicht um "async" als Schnlüsselwort sondern im async ganz allgemein im Sinne von asynchroner Ausführung von Methoden.

  • MethodA ruft MethodeB auf.
  • Es wird erst zu MethodeA zurück gekehrt wenn MethodeB komplett abgearbeitet ist.
  • Die Zeit vom Einstieg in MethodeB bis zur Rückkehr entspricht also der gesamten Zeit die zur Ausführung der gesamten MethodeB notwendig ist.

ODER

  • MethodA ruft MethodeB auf.
  • MethodeB führt nur einen kleinen Teil ihrer Arbeit synchron aus. Dann wird ein async Aufruf gestartet.
  • Während B noch auf die Antwort des async Aufrufes wartet geht es zurück zu A
  • Die Zeit vom Einstieg in MethodeB bis zur Rückkehr entspricht also der nur der Zeit die B bis zum async Aufruf benötigt.

Warum ist Fall 2 nicht schneller als Fall 1? A wartet ja bei Fall 2 nicht auf B...

Unabhängig davon:
Warum ist Fall 2 deutlich schneller als Fall 1 wenn der async Aufruf in B künstlich verlangsamt wird?

21.11.2013 - 10:12 Uhr

Hallo,

In einer Windows Phone App werden nach einem Button-Klick einige Aktualisierungen in eine SQLite Datenbank geschrieben. Der Datenbank zugriff dauert etwas, so dass die UI in Summe ein paar Sekunden einfriert.

Das soll verhindert werden in dem das Schreiben asynchron ausgeführt wird. Allerdings gelingt das nicht:

Das ist natürlich nicht schön, weshalb ich das Schreiben nun asynchron aufrufe. Allerdings wird das Ganze hierdurch nicht schneller und die UI friert immer noch ein:


public void ApplyChanges() {
   foreach (item in ItemsList) {
      IrgendwelcheÄnderungenAnItem(item);

      int startTicks = System.Environment.TickCount;

      WriteItem(item);

      int endTicks = System.Environment.TickCount;
      Debug.WriteLine("Total Time = " + (endTicks - startTicks));
   }
}

// Das async-Keyword wird nur verwendet, wenn die Methode await ExecAsync verwendet. Daher hier in Klammern...
public (async) void WriteItem(MyItem item) {
   ...
   SQLStatement sql = ItemToStatement(item);

   Exec(sql);

   // ODER

   await ExecAsync(sql);
   ...
}

public bool Exec(SQLStatement sql) {
   ...
}

public Task<bool> ExecAsync(SQLStatement sql) {
   return Task.Run(() => {
      //System.Threading.Thread.Sleep(1000);
      return Exec(sql);
   });
}

In der Methode ApplyChanges() wird also gemessen wie lange es bis zur Rückkehr aus aus WriteItem() dauert. WriteItem() führt das Schreiben dabei entweder synchron oder asynchron durch. Entsprechend wird vor der Rückkehr also auf das Ende des Schreibens gewartet oder nicht.

Ergebnis 1:
Ich habe nun erwartet, dass sich bei der async Ausführung deutlich kürze Zeiten zeigen. Das ist aber NICHT so. In beiden Fällen wird je Item eine TotalTime zwischen 150 und 250 ausgegeben.

Meine Vermutung war, dass der **Overhead **für das Erzeugen der Async-Operation ggf. ähnlich lange dauert wie die synchrone Ausführung des Schreibens. Dann hätte ich natürlich nichts gewonnen. Um das zu testen habe ich in ExecAsync() eine künstliche Verzögerung eingebaut. Wäre der Overhead schuld müsste die Zeiten unabhängig davon sein wie lange die synchrone Ausführung tatsächlich dauert.

Ergebnis 2:
Wird ExecAsync() künstlich verzögert geht auf einmal alles blitzschnell. Als TotalTime wird nun für jedes Item nur noch 10-15 angegeben.

Wie kann das sein?

Nach dem Einfügen der künstlichen Verzögerung funktioniert das Ganze so wie ich mir das vorstelle: Die Änderungen werden sehr schnell angestoßen. Der UI Thread ist sofort wieder frei während das Schreiben im Hintergrund ausgeführt wird. Aber warum ist das nur so, wenn das Ganze künstlich Verzögert wird?

30.10.2013 - 12:18 Uhr

Hallo,

ich arbeite mich gerade durch ein Beispiel und bin dort auf eine Besonderheit gestoßen. Bei Bedingungen wird dort immer auf (null == object) statt (object == null) getestet. Also z.B.


if (null == someObject) {
   someObject = new SomeObject();
   ...
}

Hat das irgendeine Bedeutung oder ist das nur der Stil des Programmierers?

29.10.2013 - 19:44 Uhr

Hallo,

ich arbeite an der Portierung einer iOS App zu WP8. Die Texte der iOS App verteilen sich auf mehrere .strings Dateien. Es gibt z.B. eine Datei app.strings mit allen Texten die nur diese App betreffen und eine Datei common.strings mit Texten die auch in anderen Apps verwendet werden.

Im Code kann ich dann z.B. StringID_123 ansprechen und das System sucht automatisch in allen .strings Dateien nach dem passenden Text. Ich muss mich also nicht explizit darum kümmern wo genau dieser Text liegt.

Dieses System hätte ich gerne auch unter WP8. Das System hier ist aber etwas komplizierter:

  • Es gibt nur eine AppResources.resx. Hieraus wird automatisch die Klasse AppResources (in AppResources.Designer.cs) erstellt.
  • Die Klasse LocalizedString macht den Zugriff auf AppResources als StaticResource möglich.
  • In XAML kann man sich dann an LocalizedStrings binden.

In C# wäre es kein Problem eine Zwischenebene zu bauen die die Suche in unterschiedlichen Dateien ermöglicht. AppResources verwenden z.B. einen ResourceManager um einen String mit ID 123 zu suchen. Ist ein solcher nicht vorhanden wird ein leeres Ergebnis zurück gegeben. Man könnte also einfach mit einem ResourceManager in App.resx suchen und mit einem weiteren ResourceManager in Common.resx falls die erste Abfrage erfolglos war.

Wie verwende ich so etwas aber mit Bindings in XAML?

Gibt es eine Möglichkeit in einer Klasse auf ein eingehendes Binding zu reagieren? Wenn also z.B. mit dem Binding "String123" angefragt wird nicht den Wert einer gleichnamigen Property zu liefern sondern eine Methode auszuführen?

29.10.2013 - 13:20 Uhr

Ich habe leider immer noch nicht herausgefunden welchen Fehler ich hier mache. Jemand eine Idee?

28.10.2013 - 15:50 Uhr

Hallo,

ich bin etwas verwirrt, wie das Tombstoning bei Windows Phone 8 umgesetzt wird. Ich habe mehrere Anleitungen gefunden (z.B. die JumpStart Videos von dev.windowsphone.com), die beschreiben wie die aktuelle Seite der App ihren Status speichert wenn die App verlassen wird um diesen später ggf. wiederherstellen zu können.

Das Problem: Die Art und Weise wie festgestellt wird, dass die App verlassen wird, ist falsch bzw. funktioniert bei mir nicht.


protected override void OnNavigatedFrom(NavigationEventArgs e) {
   base.OnNavigatedFrom(e);

   if (e.NavigationMode != NavigationMode.Back && e.NavigationMode != NavigationMode.Forward) {
      // App wurde verlassen --> Speichern
   }
}

Wenn man also weder vorwärts zur nächsten Seite noch zurück zur vorherigen Seite geht wird die App verlassen. Klingt logisch, macht aber mit der Beschreibung von NavigationMode nicht viel Sinn:

NavigationMode.Back
Navigating back to the most recent content in back navigation history. This occurs when the GoBack method is called.

NavigationMode.Forward
Navigating to the most recent content on forward navigation history. This occurs when the GoForward method is called.

NavigationMode.New
Navigating to new content. This occurs when the Navigate method is called, or when Source property is set.

Demnach wird also NavigationMode.Forward nur aufgerufen, wenn NavigationService.GoForward() benutzt wurde um auf die Seite zu gelangen. Das ist aber doch gar nicht möglich, weil es bei WP8 keine nächste Seite auf dem Stack gibt (sonst wäre es ja auch kein Stack...). Bei der Navigation auf Webseiten mag das Sinn machen, bei WP8 nicht. Dort verwende ich NavigationService.Navigate(...) um zur nächsten Seite zu gelangen. Ist das falsch?

e.NavigationMode ist beim Verlassen der Seite bei meinen Test eigentlich immer NavigationMode.New. Egal ob über .Navigate(...) die Seite aufgerufen oder die App über die Windows-Taste verlassen wird.

Mich wundert, dass das beschriebene Vorgehen von mehreren Quellen als Referenz angegeben wird. Erzählen die alle Quatsch, oder (was wohl wahrscheinlicher ist) sehe ich etwas falsch? Wo liegt der Fehler?

Vielen Dank!

28.10.2013 - 11:09 Uhr

Hallo,

ich habe eine generell Frage zur Aufgabenverteilung zwischen View und ViewModel:

Model:
Objekt Person mit Name, Abteilung, etc.

ViewModel:
Bereitet die Daten aus eines Person-Objektes für die Nutzung in einer View auf. (In diesem einfachen Beispiel natürlich eigentlich überflüssig. Könnte Person auch direkt liefern...)

View:
Bearbeitung einer Person. Name und Abteilung können geändert werden.

Klickt man in der View das Feld für die Abteilung an soll eine neue View erscheinen, in der dann die Abteilung für die Person gewählt werden kann.

Wie/Wo genau findet diese Bearbeitung am statt? Klar, die Bearbeitung des Klicks läuft erst einmal im CodeBehind der View. Dann muss eine neue View für die Auswahl der Abteilung aufgerufen werden. Geht dieser reicht der CodeBehind die Anfrage and das ViewModel weiter (z.B. .SelectDepartment()) und die Auswahl wird dann von dort aufgerufen?

Im ersten Fall (CodeBehind ruft Auswahl auf) müsste die Rückgabe ja auch irgendwie vom CodeBehind an das eigene ViewModel weiter gegeben werden. Außerdem müsste die View damit quasi wissen wie Abteilungen ausgewählt werden, also Logik ausführen. Ich vermute daher Fall 2 ist korrekt. Richtig?

25.10.2013 - 13:37 Uhr

die .suo-Dateien sind versteckt. In den Ordner-Eigenschaften von Windows kannst du diese einblenden lassen.

Danke für den Hinweis. Hab die Datei gefunden und entfernt. Leider kein Erfolg. Das Projekt startet immer noch nicht.

Ansonsten kannst du ja die im Unterordner die .csproj-Datei aufrufen

Was genau meinst du damit? Wenn ich die .csproj Datei direkt aufrufe startet das Projekt auch nicht.

25.10.2013 - 12:59 Uhr

Hallo,

ich verwende VS2012 und eines meiner Projekte lässt sich nicht mehr öffnen. Eben habe ich noch ganz normal damit gearbeitet, es gespeichert und geschlossen. Nun stürzt VS jedes Mal ab, wenn ich das Projekt öffnen möchte. Egal ob ich das Projekt direkt per Doppelklick aus dem Explorer oder in VS starte.

Mal friert VS noch beim Starten ein, mal erst wenn das Projekt schon im Projektmappenexplorer angezeigt wird.

Andere Projekte lassen sich ohne Probleme öffnen oder neu anlegen. Nur bei diesem einen Projekt gibt es Probleme. Es handelt sich um ein Projekt für Windows Phone 8. Andere WP8 Projekte machen wie gesagt keine Probleme. An dem Projekt gibt es eigentlich nichts besonderes.

Lässt sich irgendwie herausfinden woran genau VS scheitert? Kann man ein Projekt irgendwie reparieren?

Meine Suche brachte nur Ergebnisse zu ähnlichen Problemen mit VS 2010. Dort wird immer empfohlen die .suo Dateien im Projektverzeichnis zu löschen. Solche Dateien gibt es in dem Projekt aber gar nicht.

Jemand eine Idee, wie ich das Projekt retten kann?

24.10.2013 - 16:17 Uhr

Hallo,

es geht um eine App für Windows Phone 8. Ein Wert aus einem Binding wird im LongListSelector nicht korrekt angezeigt/aufgelöst. Anderswo auf der Seite aber schon. Warum?


<phone:PhoneApplicationPage
    ...>

    <Grid x:Name="LayoutRoot" DataContext="{Binding}">
        <!-- Binding wird angezeigt -->
        <TextBlock Text="{Binding Title}"/>

        <phone:LongListSelector ItemsSource="{Binding Items}">
            <phone:LongListSelector.ListHeaderTemplate>
                ...
                   <!-- Binding wird NICHT angezeigt -->
                   <TextBlock Text="{Binding Title}"/>
                ....
            </phone:LongListSelector.ListHeaderTemplate>

            <phone:LongListSelector.ItemTemplate>
                ...
                   <!-- Binding wird angezeigt -->
                   <TextBlock Text="{Binding ItemName}"/>
                ....
            </phone:LongListSelector.ItemTemplate>

        </phone:LongListSelector>
    </Grid>

Zur Laufzeit weise ich dem DataContext des LayoutRoots das konkrete ViewModel zu. Der TextBlock außerhalb des LongListSelectors zeigt {Binding Title} korrekt an. Der TextBlock im Header der Liste bleibt aber leer. Gleichzeitig funktioniert das Binding generell aber auch in der Liste, denn {Binding ItemName} funktioniert bei den einzelnen Elementen ohne Probleme.

Wo mache ich einen Fehler?

Vielen Dank!

23.10.2013 - 15:22 Uhr

Hallo,

in verschiedenen Tutorials wird der lokalisierte Text in den XAML kurz und knapp angesprochen:

{Binding LocalizedResources.StringName}

Das funktioniert bei mir nicht. Es wird nur dann etwas angezeigt, wenn ich Variante aus einem Beispiel aus dem automatisch erstellten Quelltext verwende:

{Binding Path=LocalizedResources.StringName, Source={StaticResource LocalizedStrings}}

Das ist natürlich kein Beinbruch aber die knappe Schreibweise finde ich doch deutlich übersichtlicher.

23.10.2013 - 13:13 Uhr

Hallo,

In einer WP8 App gibt es zahlreiche verschiedene Einstellungen die als gruppierte Liste angezeigt werden sollen. Jeder Eintrag führt dann zu einer Seite auf der die jeweiligen Einstellungen vorgenommen werden können.

Ich überlege nun wie ich die Liste am Besten darstellen soll:

Ansatz 1: StackPanel oder Grid mit einer ScrollView
Ich verwende einfach einen StackPane oder Grid in einer ScrollView und füge für jeden Menüpunkt bzw. für jede Gruppe ein entsprechendes Element hinzu direkt in XAML hinzu. Da die Liste statisch ist, also zur Laufzeit nie geändert wird, ist das kein Problem.

Ansatz 2: LongListSelector
Eigentlich ist der LongSelector für eine große, dynamische Datenmenge gedacht. Ihn auf eine statische Liste mit Einstellungen los zu lassen ist also vielleicht etwas Overkill. Man muss eine eigene ViewModel Klasse erstellen um den LLS mit Daten zu füttern (oder kann man die Elemente auch in XAML direkt angeben?). Dafür bekommt man die Funktion für die nicht mit-scrollenden Gruppenheader und die Jumpliste quasi kostenlos dazu.

Welchen Weg würdet ihr wählen?

23.10.2013 - 10:36 Uhr

Hallo,

Es geht um ein Projekt für Windows Phone 8. Ich habe eine ganze Menge von einfachen Icons (nur Konturen, keine Farben, etc.) im Illustrator .ai Vektor Formt. Diese würde ich gerne an verschiedenen Stellen der App in verschiedenen Größen, etc. verwenden.

Mit Blend konnte ich die .ai Datei importieren und daraus automatisch XAML generieren. Das Ganze habe ich dann als ResourceDictionary in einer eigenen XAML Datei "Icons.xaml" gespeichert:


<ResourceDictionary 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >

    <Canvas x:Name="TestIcon" Height="27.985" Canvas.Left="5.506" Canvas.Top="2.007" Width="20.988">
        <Path Data="F1M26.992,21.488L26.899,21.488C26.538,22.892 25.005,24.217 22.914,24.75 20.205,25.439 17.598,24.538 17.091,22.736 16.583,20.934 18.367,18.915 21.074,18.225 22.509,17.86 23.911,17.945 24.993,18.37L24.993,4.497C24.993,4.221 24.769,3.997 24.493,3.997 24.473,3.997 24.456,4.007 24.436,4.009L24.435,4.001 11.443,5.5 11.444,5.508C11.196,5.537,11,5.74,11,5.996L11,23.486 10.908,23.486C10.547,24.891 9.013,26.217 6.923,26.749 4.215,27.438 1.608,26.537 1.099,24.735 0.592,22.933 2.375,20.914 5.083,20.224 6.518,19.859 7.92,19.943 9.001,20.369L9.001,2.948 26.992,1.055z M27.491,0C27.473,0,27.457,0.009,27.439,0.01L27.439,0.003 8.45,2.001 8.45,2.009C8.2,2.036,8.002,2.24,8.002,2.498L8.002,19.088C7.013,18.935 5.924,18.977 4.821,19.259 1.571,20.093 -0.534,22.662 0.118,24.997 0.772,27.331 3.936,28.548 7.185,27.714 9.74,27.057 11.581,25.33 11.937,23.486L12,23.486 12,22.948C12.002,22.886,12.001,22.822,12,22.758L12,6.442 23.993,5.058 23.993,17.089C23.005,16.936 21.914,16.978 20.811,17.261 17.562,18.095 15.457,20.664 16.11,22.998 16.763,25.332 19.928,26.549 23.177,25.715 25.731,25.059 27.571,23.331 27.928,21.488L27.991,21.488 27.991,20.949C27.993,20.886,27.992,20.823,27.991,20.761L27.991,0.499C27.991,0.223,27.767,0,27.491,0" Fill="#FF376EB5" Height="27.977" Canvas.Left="0" Stretch="None" Canvas.Top="0" Width="27.993">
            <Path.Clip>
                <RectangleGeometry Rect="0,-0.001,27.992,27.977"/>
            </Path.Clip>
        </Path>
    </Canvas>

</ResourceDictionary>

Problem 1: Wie greife ich in einer beliebigen anderen XAML Datei auf die Icons.xaml zu, so dass ich dort z.B. TestIcon verwenden kann?

Bislang habe ich es nur geschafft TestIcon direkt in der XAML Datei zu verwenden in er ich es auch definiert habe:


<phone:PhoneApplicationPage
    ...>

    <phone:PhoneApplicationPage.Resources>
        <Canvas x:Name="TestIcon"...>
            ....
        </Canvas>
    </phone:PhoneApplicationPage.Resources>

    ...

    <Button ...>
        <ContentPresenter Height="32" Width="32" Content="{StaticResource TestIcon}" />
    </Button>

</phone:PhoneApplicationPage>

Problem 2: Wie spreche ich die so definierte StaticResource als Bindign an?


    <Button ...>
        <ContentPresenter Height="32" Width="32" Content="{Binding IconName}" />
    </Button>

Wenn das Binding hier als IconName "TestIcon" liefert, funktioniert das nicht. Wie wird das korrekt angegeben?

Problem 3: Wie kann ich das Icon auf Button 1 mit Farbe A und auf Button 2 mit Farbe B verwenden? Bislang bestimmt die Fill-Eigenschaft des Path die Farbe. Damit hat das Icon dann aber überall die gleiche Farbe.

Problem 4: Wie kann ich das Icon als Source für ein Image verwenden? Ich habe dazu nur die Information gefunden, dass man das Icon statt auf einer Canvas als DrawingImage angeben sollte. Das scheint aber nur bei WPF zu funktionieren, während mir DrawingImage bei meinem Windows Phone 8 Projekt immer als unbekannt angezeigt wird. Wie ist hier das korrekte vorgehen?

Vielen Dank!

18.10.2013 - 16:23 Uhr

Hallo,

in einer Windows Phone 8 App benötige ich ein Steuerlement, dass die Eingabe von Text in einem ganz bestimmen Format ermöglicht. Im Konkreten Fall geht es um Seriennummern aus Zahlen und bestimmen Buchstaben.

Für die Eingabe soll keine interne Tastatur verwendet werden, da es für die Seriennummern keine passende gibt. Stattdessen sollen einfach ein paar Buttons mit den passenden Zahlen und Buchstaben verwendet werden.

**Problem bei einer TextBox: **
Ich habe keinen Weg gefunden diese zu aktivieren (Cursor blinkt und kann per Code verschoben werden, Eingabe möglich), ohne dass eine Tastatur eingeblendet wird. Ist das Möglich? Zudem müssten die Funktionen für das Markieren, Copy&Paste in diesem Fall deaktiviert werden. Ich glaube, dass ist bei der TextBox zwar möglich aber nicht so einfach.

Also:
Eigentlich geht es nur darum ein Steuerelement zu basteln, dass Zahlen, bestimmte Buchstaben (kurz: einen Text) und einen Cursor anzeigen kann. Die Anzeige des Textes ist natürlich kein Problem. Dafür kann man quasi einen TextBlock verwenden. Dabei fehlt aber der ganze entscheidende Cursor.

Da zur Einhaltung des Formates der Inhalt strikt von Code kontrolliert wird wäre es die einfachste Lösung den Cursor im Text zu positionieren. Angenommen es geht um Zahlen mit zwei Nachkommastellen. Dann hat ein "leeres" Feld einfach den Text "0|.00". Wird ein Komma eingegeben springt der Cursor entsprechend weiter: "0.0|0". Die Lösung sehr einfach und sehr unschön. Da der Cursor ein eigenes Zeichen ist statt zwischen den Zeichen zu stehen, springen die Zeichen wenn der Cursor bewegt wird. Zudem ist der Cursor statisch und Blinkt nicht.

Ich müsste also einen echten Cursor zeichnen können statt diesen über ein Zeichen darzustellen. Zudem müsste der Cursor blinken können. Wie macht man so was?

Wäre eine Unterklasse von TextBox der beste Weg? Oder doch eine ganze eigene Klasse, die den Text quasi selber zeichnet? Da dies meine erstes eigenes Steuerelement wird, bin ich unsicher was die beste Herangehensweise ist und möchte mich nicht in einer Sackgasse verlaufen. Ich bin daher für jeden Tipp dankbar.

18.10.2013 - 14:22 Uhr

Hallo,

ich arbeite an einem W8 Projekt und habe diesem das Windows Phone ToolKit hinzugefügt. Darin sind auch verschiedene neue Controls vorhanden die es sonst nicht gibt. Diese würde ich nun gerne direkt aus dem Werkzeugkasten heraus im Designer verwenden können.

Ich habe auch verschiedene Anleitungen gefunden nach denen dies möglich sein sollte. Das Vorgehen ist immer gleich:

  1. Rechtsklick Im WerkzeugkastenRegisterkarte hinzufügen
  2. Rechtsklick in den neuen Tab und "Elemente auswählen" wählen.
  3. Die Microsoft.Phone.Controls.Toolkit.dll im Projektverzeichnis suchen und auswählen
  4. Übernehmen und die Controls sind im neuen Tab

Ich erhalte dabei jedoch die Meldung, dass die DLL keine Controls enthält:

Fehlermeldung:
In "...\Microsoft.Phone.Controls.Toolkit.dll" sind keine Komponenten vorhanden, die im Werkzeugkasten positioniert werden können.

Arbeitet hier ggf. jemand mit dem ToolKit und kennt das Problem? Konnten die Control bei euch eingefügt werden oder gibt es einen anderen Weg?

Vielen Dank!

17.10.2013 - 13:10 Uhr

Vielen Dank für die Antwort! Dann bleibe ich wohl dabei beim Auslösen des Events die eigenen EventArgs zu erstellen und die Empfänger müssen die dann wenn gewünscht selber casten. Das erscheint mir sauberer.

17.10.2013 - 12:42 Uhr

Hallo,

Eine Klasse implementiert INotifyPropertyChanged und bietet entsprechend das Event PropertyChangedEventHandler PropertyChanged an. Hierbei ist PropertyChangedEventHandler definiert als:

public delegate void PropertyChangedEventHandler(object sender, PropertyChangedEventArgs e)

Die PropertyChangedEventArgs übertragen dabei nur den Namen der geänderten Property. Ich würde das Ganze nun gerne so erweitern, dass zusätzlich auch der alte und der neue Wert der Property übermittelt werden:


public class MyPropertyChangedEventArgs : PropertyChangedEventArgs {
    // OldValue und NewValue hinzufügen...
}

Nun ist es natürlich kein Problem beim Auslösen des Events MyPropertyChangedEventArgs statt PropertyChangedEventArgs zu erstellen, diese entsprechend zu füllen und an den PropertyChangedEventHandler zu übergeben. Damit muss aber jeder Handler des Events die Argument nach MyPropertyChangedEventArgs casten um auf OldValue und NewValue zugreifen zu können.

Besser wäre es, wenn das Event direkt die Argumente vom richtigen Typ übertragen würde:


public delegate void MyPropertyChangedEventHandler(object sender, MyPropertyChangedEventArgs e);

public class MyObject: INotifyPropertyChanged {
    // Hier wird MyPropertyChangedEventHandler statt PropertyChangedEventHandler verwendet --> Fehler --> INotifyPropertyChanged  nicht implementiert
        public event MyPropertyChangedEventHandler PropertyChanged;

    ...
}

MyPropertyChangedEventHandler ist quasi eine Spezialisierung von PropertyChangedEventHandler, aber das sieht der Compiler nicht.

Gibt es eine Möglichkeit, wie man statt PropertyChangedEventHandler einen "geerbten" MyPropertyChangedEventHandler verwendet?

17.10.2013 - 10:56 Uhr

Ah, vielen Dank. Das war unter den ganzen Möglichkeiten die ausprobiert hatte noch nicht dabei 😃

17.10.2013 - 10:32 Uhr

Hallo!

Ich will eine generische Klasse definieren deren TElementType auf ein Interface eingeschränkt ist. Zudem soll die Klasse selbst noch mehrere Interfaces implementieren. Wie macht man das?


public class GUIDDictionary<TElementType> : Dictionary<Guid, TElementType> where TElementType : IGuidIdentifiedObject, ISomeInterface {
    ...
}

Es sollen also nur Element zugelassen sein, die IGuidIdentifiedObject implementieren. Soweit alles OK. Zudem soll GUIDDictionary<> das Interface ISomeInterface implementieren.

Die Definition oben ist falsch, denn ISomeInterface bezieht sich hier auf die Einschränkung des TElementType und nicht auf GUIDDictionary<>.

Aber wie definiere ich das Richtig? In den Erklärungen der generischen Klassen wird dieser Fall nicht behandelt. Lässt sich das überhaupt definieren?

17.10.2013 - 10:24 Uhr

Super. Ganz herzlichen Dank!

15.10.2013 - 16:05 Uhr

Noch eine Nachfrage:
Es geht um den korrekten Aufruf einer async Methode auf deren Ende nicht gewartet werden soll. Hierbei gibt der Compiler eine Warnung aus:

Fehlermeldung:
Da auf diesen Aufruf nicht gewartet wird, wird die Ausführung der aktuellen Methode vor Abschluss des Aufrufs fortgesetzt. Ziehen Sie ein Anwenden des 'Await'-Operators auf das Ergebnis des Aufrufs in Betracht.

Beispiel: Ein Objekt DataCenter lädt bei der Erstellung Datensätze über Personen aus einer Datenbank. Das Laden dauert eine Weile und wird daher in einem separaten Thread erledigt. Das DataCenter Object kann schon vorher verwendet werden und wartet daher nicht auf das Laden der Daten:


DataCenter dataCenter = new DataCenter();

... 
public class DataCenter {
   public DataCenter() {
      ...
      State = DataCenterState.NotLoaded;
      LoadPersonsAsync();  // <-- Compiler Warnung
   }

   private async Task LoadPersonsAsync {
      State = DataCenterState.Loading;

      List<Person> = await LoadFromDBAsync(...);
      ...
      State = DataCenterState.Loaded;
   }
}

Die Warnung ist natürlich richtig (DataCenter() wartet nicht und die Bearbeitung wird fortgesetzt). Das ist an der Stelle aber durchaus gewünscht. Kann man die Warnung irgendwie deaktivieren? Oder verwende ich das TAP hier falsch?

15.10.2013 - 14:01 Uhr

Das es das Konzept weiterhin gibt und dieses nicht einfach verworfen wird ist klar. Wie gesagt geht es ja auch nur um die Frage der Relevanz in der Praxis.

Ich habe entdeckt, dass das Ganze auch in Jump-Start Videos bei MSDN angesprochen wird. Die Logik dabei ist:

  • Eine App im Dormant-State wird Tombstoned wenn der Speicher knapp wird.
  • Auf aktuellen Geräten ist die Wahrscheinlichkeit, dass der Speicher knapp wird gering.
  • Wird eine App Tombstoned war sie schon lange nicht mehr aktiv. Es werden max. 5 Apps Tombstoned bis begonnen wird die älteste App im Tombstone-State zu schließen. Die Wahrscheinlichkeit, dass eine App nach dem Tombstoning geschlossen wird ist hoch. Die Wahrscheinlichkeit, dass eine App nach dem Tombstoning gestartet wird ist gering.
  • Die App war also schon länger inaktiv. Der Nutzen, dass die App beim nächsten Zugriff an der letzten Stelle startet ist gering, da er sich eh nicht mehr daran erinnern kann wo er zuletzt in der App war...

Ob die Logik für die eigene App gilt hängt vermutlich stark von der Zielgruppe (auch schwache Geräte dabei?) und der Funktion der App (Fortsetzen an der letzten Stelle sinnvoll?) ab...

15.10.2013 - 09:45 Uhr

Mittlerweile konnte ich einen Artikel von MS finden, der IsApplicationInstancePreserved genauer beschriebt. Die Doku selbst sagt nur, dass der Wert true ist, wenn die App wiederhergestellt wurde. Ich habe das so verstanden, dass der Wert true ist, wenn die App aus dem Tombstoning wiederhergestellt wurde. Das verträgt sich aber wie gesagt nicht mit den Beobachtungen bei der Nutzung der Debug-Option.

Der Wert ist true wenn, wenn die App aus dem Dormant-State wiederhergestellt, also reaktiviert, wurde. Befand sich die App nicht mehr im Speicher kann sie von dort nicht wiederhergestellt werden und der Wert ist false. Das deckt sich dann auch mit den Beobachtungen. Wie ich finde recht missverständlich ausgedrückt, aber OK 😃

Was bleibt ist die Frage, ob Tombstoning noch aktuell/relevant ist. Dass es die Funktion weiterhin gibt steht wie gesagt außer Frage. Mich verwirren nur die Artikel die sagen, dass die Funktion in der Praxis eigentlich nicht mehr relevant ist. Stimmt das?

14.10.2013 - 17:16 Uhr

Hallo,

ich beschäftige mich gerade mit dem Tombstoning einer WP 8 App. Zunächst eine Verständnisfrage:

Eigentlich alle Quellen die ich zum Tombstoning gefunden habe, beziehen sich auf WP 7. Ein Beitrag schreibt zudem, dass Tombstoning mit dem Multitasking seit WP Mango eigentlich irrelevant sei. Es wäre zwar weiterhin möglich, dass eine App vom Dormant-State in den Tombstoned-State übergehet. Das würde aber nur so selten passieren, dass man dies vernachlässigen könnte. Stimmt das?

Wie dem auch sei, ich würde die Funktion gerne testen. In den Projekteinstellungen in VS gibt es hierzu unter "Debugging" die Option "Tombstone bei Deaktivierung während des Debuggens". Ich habe die Option so verstanden, dass die App hiermit bei der Deaktivierung ins Tombstoning versetzt wird statt nur deaktiviert zu sein? Ist das richtig?

Dann müsste die App bei der Reaktivierung nicht nicht nur reaktiviert sondern auch aus dem Tombstoning wiederhergestellt werden. Wenn ich das richtig verstanden habe spiegelt sich dies im Application_Activated Event in den EventArgs im Feld IsApplicationInstancePreserved. Dieses ist true, wenn die App bei **deaktivierter **Tombstone-Debugg-Funktion reaktiviert wird und ansonsten false.

Müsste das nicht genau umgekehrt sein? Die Tombstone-Funktion heißt doch, dass ein App-Status gespeichert wird, der wiederhergestellt werden kann.

An welcher Stelle sehe ich das falsch?

09.10.2013 - 09:46 Uhr

Hallo,

in einem Windows Phone 8 Projekt verwende ich sqlite-winrt um auf eine SQLite Datenbank zuzugreifen.

Dabei ist mir aufgefallen, dass PrepareStatementAsync(query) eine Exception auslöst, wenn query zwar korrekt ist aber nicht ausgeführt werden kann.

Konkret geht es bei mir um ein ein Query um einen Trigger zu erstellen:


Statement sqlStatement = await db.PrepareStatementAsync("CREATE TRIGGER MyTrigger...");
sqlStatement.StepAsync();

Der Aufruf läuft ohne Probleme, wenn MyTrigger in der Datenbank noch nicht existiert. Das sqlStatement wird also korrekt erstellt. Hierdurch wird der Trigger natürlich noch nicht angelegt. Das passiert erst durch das dann folgende sqlStatement.StepAsync().

Existiert der Trigger der Datenbank jedoch schon, kommt es bereits in PrepareStatementAsync(...) zur Exeption. Warum?

Ich würde verstehen, wenn in diesem Fall sqlStatement.StepAsync() einen Fehler liefert (vielleicht nicht unbedingt als Exception) denn der Trigger kann nicht zweimal erstellt werden. Aber PrepareStatementAsync(...) führt doch an der Datenbank noch keinerlei Änderungen durch, sondern erstellt nur aus dem Query ein Statement.

Ist einfach "schlau" und weiß "Hey, die Ausführung eines Statments mit diesem Query wird zu einem Fehler führen, darum kann ich diesen auch jetzt schon melden"? Oder mache ich irgendwas falsch?

09.10.2013 - 09:31 Uhr

Nochmals vielen Dank für die ausführliche Antwort! Ich denke ich sehe jetzt schon etwas klarer, werde mich aber auf jeden Fall noch weiter in die Beschreibungen vertiefen.

Bei APM und EAP erhält der Aufrufer durch einen Callback oder ein Event die Nachricht, dass die Aufgabe abgearbeitet wurde. Beim TPL läuft statt dessen einfach der Code hinter dem await weiter. Dies geschieht zudem automatisch im Aufruf-Thread, es sei denn man unterbindet dies durch ConfigureAwait(false).

Habe ich das jetzt soweit richtig verstanden?

Es wurde ja schon gesagt, dass async/await viral ist. Dahinter verbirgt sich nichts anderes, als das von mir beobachtete Phänomen, dass ein Einsatz von async/await dazu führt, dass man das quasi durch den kompletten Code bis zum ersten Aufruf durchziehen muss wenn der Aufruf auf das Ergebnis des Task angewiesen ist. Richtig?

08.10.2013 - 17:13 Uhr

Naja, ich glaub Du hast es nicht verstanden 😉

Da sind wir uns einig 😃

Dein Code bringt quasi nichts, keinerlei Vorteile. Erst wenn Du um das async/await etwas drumrum baust (zB während dem Verbindungsaufbau irgendwas anderes machen kannst) macht es sinn.

Naja, es sollte klar sein dass es nur ein Beispiel ist. Es geht ja nicht nur um den Verbindungsaufbau sondern um die gesamte Verwendung der Datenbank. Jede Abfrage ist nur über async-Methoden möglich.

Angenommen die Verbindung steht und der Nutzer startet eine Funktion zum Laden irgendwelcher großer Daten aus der DB. Während die Daten laden kann der Nutzer sonstwas machen. Aber woher weiß die App, dass die Daten vollständig geladen wurden und diese angezeigt oder bearbeitet werden können?

Einfaches Beispiel, wieso async/await viel Code spart. (...)

Wenn ich das Beispiel richtig verstehe geht es um die Abarbeitung von Aufgaben deren Ende für den Rest des Programms egal sind. Die Aufgabe "Mail verschicken" kann man z.B. leichter asynchron gestalten als "Mail empfangen". Wann genau die Mail weg ist, ist (theoretisch) egal. Aber wenn man eine Mail empfängt will man auch wissen wann man mit dieser Arbeiten kann.

Warum Dein Code schrecklich ist:
Wenn Du ne Methode hast, die suggeriert, dass sie nur eine Connection durchführt, dann sollte auch dessen Inhalt so sein.

Viel eher sollte Dein Code also so aussehen:

  
public Task ConnectAsync() {  
    return database.OpenAsync();  
 }   
  

Wie gesagt, es war nur ein Beispiel. Man kann das auch allgemein kurz zusammenfassen:

  • Wenn man eine asynchrone Methode ausführt bekommt man das Ergebnis irgendwann später.
  • Interessiert einen das Ergebnis des Aufrufs (oder auch nur die Information, dass der Aufruf komplett ist), muss man irgendwie darüber benachrichtigt werden.
  • Wie geht das mit TPL. Geht das überhaupt mit TPL oder verwendet man dafür ein anderes Pattern?
08.10.2013 - 16:46 Uhr

Das ist natürlich möglich. Es ist aber so, dass die Lokalisierung immer als .strings geliefert werden (das ist einfach der etablierte Projektablauf). Ich müsste also bei jeder Änderung eine Konvertierung .strings -> ... -> .resx haben.

.strings in CSV zu konvertieren ist mit Suchen/Ersetzten natürlich nicht schwierig. Natürlich kann man sich auch ein Skipt/Programm schreiben, dass das automatisch erledigt.

Da dies aber wie gesagt vermutlich nicht das erste Projekt ist, dass von iOS auf WP kommt bin ich mir ziemlich sicher, dass es hierfür bessere/fertige Wege gibt.

Mails per Skipt/Kommandoziele vom Server abzuholen ist auch relativ einfach möglich. Vermutlich sind wir uns aber einig, dass die Verwendung eines der vielen Mailprogramme die effektivere Lösung ist.

Vielleicht täusche ich mich auch und jeder verwendet einen selbst gebastelten Weg. Dann wäre ein Tool dafür sicherlich eine Marktlücke 😃

Daher die Frage in die Runde: Wie macht ihr das?

08.10.2013 - 16:35 Uhr

Hallo,

in einem Windows Phone 8 Projekt verwende ich sqlite-winrt um auf eine SQLite Datenbank zuzugreifen. Alle wesentlichen Methoden in sqlite-winrt sind asynchron, z.B. .OpenAsync(), etc.

Nach einem ersten Thread async/await: Verständnisfrage zur Ausführung in synchronen Methoden habe ich noch einmal zusätzlich recherchiert.

Die generell Bedeutung von async und await habe ich (denke ich) verstanden, ich verstehe aber die generelle Funktion des Task-based Asynchronous Pattern (TAP) allgemein nicht.

In der Beschreibung von Microsoft (Download "Task-based Asynchronous Pattern" from Official Microsoft Download Center, DOCX-Format) wird TAP mit anderen asynchronen Pattern vergleichen.

Bei APM und EAP ist es so, dass eine synchrone Methode einen asynchronen Aufruf startet und dann irgendwann nach dessen Ende Eine Rückmeldung über einen Callback oder ein Event erhält. Man weiß also wann der asynchronen Aufruf zu Ende ist und kann entsprechend weiterarbeiten.

Genau das fehlt mir beim TAP. Wie funktioniert das hier?

Bei sqlite-winrt ist z.B. die Methode zum Herstellen der Verbindung zur Datenbank asynchron. Wäre die Methode synchron würde das Ganze z.B. so aussehen:


public void SyncMethode() {
  ...
  Connect();
  WorkWithDB();
  ...
}

public void Connect() {
   database.Open();
   InitDB(database);
   MachNochWasMitDB();
}

Da Open() synchron ausgeführt wird gibt es kein Problem. InitDB(), MachNochWasMitDB() und später WorkWithDB() wird erst ausgeführt wenn die Datenbank wirklich geöffnet werden konnte.

ABER: Open ist nicht synchron sondern steht nur als asynchrones OpenAsync() zur Verfügung:


public void SyncMethode() {
  ...
  Connect();
  WorkWithDB();
  ...
}


// Lösung1: Einfach OpenAsync verwenden
public void Connect() {
   database.OpenAsync();
   InitDB(database);
   MachNochWasMitDB();
}

// Lösung2: Connect async machen
public async Task ConnectAsync() {
   await database.OpenAsync();
   InitDB(database);
   MachNochWasMitDB();
}

Lösung1 funktioniert natürlich nicht. Nach dem Aufruf von OpenAsync() wird direkt weitergearbeitet obwohl die Verbindung (vielleicht) noch gar nicht hergestellt wurde. InitDB, etc. laufen also vermutlich ins Leere.

Lösung2 ist schon besser. Durch das await werden InitDB und MachNachWasMitDB() erst ausgeführt wenn OpenAsync() komplett ausgeführt wurde (richtig?). Gleichzeitig geht die Kontrolle nach dem Aufruf von await database.OpenAsync() aber direkt zurück an die synchrone Methode SyncMethode(). Dort wird WorkWithDB() aufgerufen obwohl diese noch gar nicht bereit ist...

Jetzt könnte man natürlich auch in SyncMethode() ein await verwenden, aber dann bekommt man das gleiche Problem in der Methode die SyncMethode() aufruft. Die Kette würde sich bis zum allerersten Aufruf im Programm fortsetzten.

Wie löst man das?

Wie erfährt SyncMethode() (oder eine andere Synchrone Methode) davon, dass ConnectAsync() vollständig ausgeführt wurde und man mit WorkWithDB() weiter machen kann?

Bei APM und EAP gäbe es wie gesagt einen Callback oder ein Event, dass entsprechend Bescheid sagen würde. Aber wie läuft das hier?

08.10.2013 - 13:54 Uhr

Hallo!

Ich arbeite an der Portierung meiner bestehenden iOS App auf Windows Phone. Die .resx Dateien die es unter VS für jede Sprache gibt, gibt es ganz ähnlich auch in Xcode. Hier werden aber .strings Dateien verwendet. Das sind einfache Textdateien mit dem Format:


"ValueName" = "Ich bin Text";
"OtherValue" = "Noch mehr Text...";
...

Generell sollte es kein Hexenwerk sein aus einer .strings-Datei eine .resx Datei zu erstellen. Dass das mit einem Script, einen einfachen Programm etc. selber gemacht werden kann ist klar. Ich will aber ungern das Rad neu erfinden.

Da dies vermutlich nicht die erste iOS App ist, die auch auf Windows Phone laufen soll, bin ich vermutlich auch nicht der Erste der vor diesem Problem steht. Wenn also schon jemand Erfahrungen damit hat, mit welchen Tools sich der Arbeitsauflauf am besten Automatisieren lässt bin ich für jeden Tipp aus der Praxis dankbar.

Ich habe zwar schon verschiede Resx-Editoren gefunden, aber diese können nur resx aus anderen Formaten, wie z.B. CSV, erstellen. Eine Lösung für .strings habe ich noch nicht gefunden.

Welche Tools verwendet ihr? Wie habt ihr den Arbeitsfluss organisiert um den Überblick zu behalten?

Vielen Dank für eure Tipps!

07.10.2013 - 17:22 Uhr

Hallo!

Ich habe einen Server gemietet auf dem verschieden Webseiten laufen. Den Server würde ich gerne zusätzlich verwenden um dort meine Projekte zu sichern. Das Ganze soll über Git laufen: Am ende eines Tages sollen also alle Änderungen am Projekt an das Git Repository auf dem Server übertragen werden.

Das ist soweit kein Problem. Allerdings speichert Git die Dateien alle unverschlüsselt ab. Ich habe den Server zwar gemietet und ich bin der Admin, aber sicher, dass bei dem Hoster keiner einen Blick riskiert kann ich natürlich nicht sein.

Gibt es eine Möglichkeit Git verschlüsselt zu verwenden? Sowohl die Übertragung als auch die gespeicherten Dateien sollten verschlüsselt sein. Ist das mit Git machbar? Ich habe bislang nichts dazu gefunden, aber vielleicht gibt es ja Tricks bei der Konfiguriaton, etc. um das möglich zu machen.

Vielen Dank

03.10.2013 - 14:55 Uhr

Hallo,

Eine Klasse hat ein Feld "Datum":


public class MyClass {
   public DateTime Date { get; set; }
}

Ich würde nun gerne im Setter des Feldes irgendwelchen zusätzlichen Code ausführen, der mit dem eigentlichen Setzen des Feldes nichts zu tun hat:


public class MyClass {
   public DateTime Date { 
      get; 
      set {
         MachIrgendWas();
      }
}

Wenn ich dies so ausführe, wird zwar MachIrgendWas() korrekt aufgerufen, Date hat aber nach der Zuweisung keinen neuen Wert. Wird der Setter explizit angegeben muss scheinbar auch die Zuweisung explizit erfolgen:


public class MyClass {
   private DateTime date;
   public DateTime Date { 
      get { return date; }
      set {
         date = value;
         MachIrgendWas();
      }
}

Man muss also zuätzlich eine private Variable einfügen, der dann im Setter explizit der Wert zugewiesen wird und die dann auch im Getter verwendet wird.

Das ist zwar kein Drama, aber auch nicht schön. Ich benötige diese private Variable nirgendwo sonst. Ich fände es daher besser, wenn diese nur vom Compiler intern verwendet wird und nicht in meinem Code auftraucht. Ist das möglich?

02.10.2013 - 14:27 Uhr

Super, vielen Dank für die ausführliche und informative Antwort! Ich werde mich damit noch einmal weiter in die Lektüre stürzen. Die verlinkte Seite ist wirklich gut. Zuvor habe ich mich an einem Blog-Artikel orientiert, der mich scheinbar mehr verwirrt als beraten hat 😃

02.10.2013 - 13:31 Uhr

Hallo,

Ich verwende sqlite-winrt um innerhalb eines Windows Phone 8 Projektes auf eine SQLite Datenbank zuzugreifen.

Alle wesentlichen Methoden in sqlite-winrt sind asynchron, z.B. .OpenAsync(), etc.

Die Datenbank in meiner App wird wirklich klein sein. Es macht daher nicht wirklich Sinn asynchron zu arbeiten weil sich alle Operationen ziemlich schnell bearbeiten lassen.

Wie verwende ich nun in meiner "synchronen App" die asynchronen Methoden von sqlite-winrt?


private async void ConntectToDatabase() {
    database = new Database(ApplicationData.Current.LocalFolder, databaseName);
    await database.OpenAsync();
}

await ist hier quasi genau das Schlüsselwort, dass ich suche. Die asynchrone Methode wird aufgerufen und auf deren Erledigung gewartet. Insgesamt arbeitet ConnectToDatabase also synchron.

Das geht aber nur, wenn die Methode durch das Hinzufügen von "async" selber als asynchron ausgezeichnet wird. Aber ist das wirklich das korrekt vorgehen?

Die Methode soll ja eben nicht asynchron sein, sondern synchron ausgeführt werden. Verstehe ich die Bedeutung des Schlüsselwortes async falsch oder ist hier die Verwendung von async und await generell falsch?

async hat ja auch noch weitere Einschränkungen. z.B. kann man die Methode nicht einfach von void auf bool ändern, weil async Methoden nur void, Task oder Task<T> liefern dürfen.

Wie verwendet mal also asynchrone Aufrufe richtig in synchronen Methoden?

01.10.2013 - 16:19 Uhr

Ich habe Apps für iOS entwickelt und das hat mich vermutlich versaut 😃

Dort wird die App auch in Form eines Paketes ausgeliefert (Bundle genannt). Darin sind alle Dateien gepackt die zu der App gehören. Bei der Installation bekommt die App einen Speicherordner zugewiesen, aus dem diese nicht heraus kommt. Also quasi genau dasselbe wie unter WP (XAP Package = App Bundle, IsolatedStorage = Sandbox Folder).

Unter iOS kopiere ich beim ersten Start die Datenbank aus dem Bundle in die Sandbox und arbeite dann dort mit dieser. Da die Konzepte ja (scheinbar) identisch sind, wollte ich nun unter WP8 genauso vorgehen.

Das die Dateien die bei der Installation automatisch kopiert werden habe ich so verstanden, dass diese automatisch vom Package in den IsolatedStorage übernommen werden. Stimmt das nicht? Gelangen diese noch an eine andere Stelle? Also ein Install-Dir?

Wenn ich dem Projekt einfach eine Datei "Test.abc" hinzufüge und angeben, dass diese kopiert werden soll. Unter welchem Pfad finde ich diese dann nach der Installation?