Browse Source

Update TripExpense to use new features

James Montemagno 10 năm trước cách đây
mục cha
commit
697a951ce1
41 tập tin đã thay đổi với 727 bổ sung615 xóa
  1. 0 22
      Demos/TripExpenses/.gitattributes
  2. 0 217
      Demos/TripExpenses/.gitignore
  3. 0 6
      Demos/TripExpenses/.nuget/NuGet.Config
  4. BIN
      Demos/TripExpenses/.nuget/NuGet.exe
  5. 0 144
      Demos/TripExpenses/.nuget/NuGet.targets
  6. 6 2
      Demos/TripExpenses/README.md
  7. 25 0
      Demos/TripExpenses/TripExpenses.UI/Converters/MultiTriggerConverter.cs
  8. 12 0
      Demos/TripExpenses/TripExpenses.UI/MyClass.cs
  9. 27 0
      Demos/TripExpenses/TripExpenses.UI/Properties/AssemblyInfo.cs
  10. 62 0
      Demos/TripExpenses/TripExpenses.UI/TripExpenses.UI.csproj
  11. 4 0
      Demos/TripExpenses/TripExpenses.UI/packages.config
  12. 129 56
      Demos/TripExpenses/TripExpenses.sln
  13. 15 0
      Demos/TripExpenses/TripExpenses.userprefs
  14. 5 1
      Demos/TripExpenses/TripExpenses/TripExpenses.Android/Properties/AndroidManifest.xml
  15. 19 12
      Demos/TripExpenses/TripExpenses/TripExpenses.Android/Resources/Resource.Designer.cs
  16. BIN
      Demos/TripExpenses/TripExpenses/TripExpenses.Android/Resources/drawable-hdpi/add.png
  17. BIN
      Demos/TripExpenses/TripExpenses/TripExpenses.Android/Resources/drawable-mdpi/add.png
  18. BIN
      Demos/TripExpenses/TripExpenses/TripExpenses.Android/Resources/drawable-xhdpi/add.png
  19. BIN
      Demos/TripExpenses/TripExpenses/TripExpenses.Android/Resources/drawable-xxhdpi/add.png
  20. 47 43
      Demos/TripExpenses/TripExpenses/TripExpenses.Android/TripExpenses.Android.csproj
  21. 2 0
      Demos/TripExpenses/TripExpenses/TripExpenses.Android/packages.config
  22. 27 5
      Demos/TripExpenses/TripExpenses/TripExpenses.WinPhone/TripExpenses.WinPhone.csproj
  23. BIN
      Demos/TripExpenses/TripExpenses/TripExpenses.WinPhone/add.png
  24. 2 0
      Demos/TripExpenses/TripExpenses/TripExpenses.WinPhone/packages.config
  25. BIN
      Demos/TripExpenses/TripExpenses/TripExpenses.iOS/Resources/add.png
  26. BIN
      Demos/TripExpenses/TripExpenses/TripExpenses.iOS/Resources/add@2x.png
  27. BIN
      Demos/TripExpenses/TripExpenses/TripExpenses.iOS/Resources/add@3x.png
  28. 45 43
      Demos/TripExpenses/TripExpenses/TripExpenses.iOS/TripExpenses.iOS.csproj
  29. 2 0
      Demos/TripExpenses/TripExpenses/TripExpenses.iOS/packages.config
  30. 18 0
      Demos/TripExpenses/TripExpenses/TripExpenses/Interfaces/IDataStore.cs
  31. 11 1
      Demos/TripExpenses/TripExpenses/TripExpenses/Models/TripExpense.cs
  32. 27 13
      Demos/TripExpenses/TripExpenses/TripExpenses/Services/AzureDataStore.cs
  33. 132 0
      Demos/TripExpenses/TripExpenses/TripExpenses/Services/XMLDataStore.cs
  34. 6 3
      Demos/TripExpenses/TripExpenses/TripExpenses/TripExpenses.Shared.projitems
  35. 2 2
      Demos/TripExpenses/TripExpenses/TripExpenses/TripExpenses.Shared.shproj
  36. 5 3
      Demos/TripExpenses/TripExpenses/TripExpenses/ViewModels/DetailViewModel.cs
  37. 43 3
      Demos/TripExpenses/TripExpenses/TripExpenses/ViewModels/ExpensesViewModel.cs
  38. 14 5
      Demos/TripExpenses/TripExpenses/TripExpenses/Views/DetailsPage.xaml
  39. 3 1
      Demos/TripExpenses/TripExpenses/TripExpenses/Views/DetailsPage.xaml.cs
  40. 25 21
      Demos/TripExpenses/TripExpenses/TripExpenses/Views/ExpenseListPage.xaml
  41. 12 12
      Demos/TripExpenses/TripExpenses/TripExpenses/Views/ExpenseListPage.xaml.cs

+ 0 - 22
Demos/TripExpenses/.gitattributes

@@ -1,22 +0,0 @@
-# Auto detect text files and perform LF normalization
-* text=auto
-
-# Custom for Visual Studio
-*.cs     diff=csharp
-*.sln    merge=union
-*.csproj merge=union
-*.vbproj merge=union
-*.fsproj merge=union
-*.dbproj merge=union
-
-# Standard to msysgit
-*.doc	 diff=astextplain
-*.DOC	 diff=astextplain
-*.docx diff=astextplain
-*.DOCX diff=astextplain
-*.dot  diff=astextplain
-*.DOT  diff=astextplain
-*.pdf  diff=astextplain
-*.PDF	 diff=astextplain
-*.rtf	 diff=astextplain
-*.RTF	 diff=astextplain

+ 0 - 217
Demos/TripExpenses/.gitignore

@@ -1,217 +0,0 @@
-#################
-## Eclipse
-#################
-
-*.pydevproject
-.project
-.metadata
-bin/
-tmp/
-*.tmp
-*.bak
-*.swp
-*~.nib
-local.properties
-.classpath
-.settings/
-.loadpath
-
-# External tool builders
-.externalToolBuilders/
-
-# Locally stored "Eclipse launch configurations"
-*.launch
-
-# CDT-specific
-.cproject
-
-# PDT-specific
-.buildpath
-
-
-#################
-## Visual Studio
-#################
-
-## Ignore Visual Studio temporary files, build results, and
-## files generated by popular Visual Studio add-ons.
-
-# User-specific files
-*.suo
-*.user
-*.sln.docstates
-
-# Build results
-
-[Dd]ebug/
-[Rr]elease/
-x64/
-build/
-[Bb]in/
-[Oo]bj/
-[Pp]ackages/
-[Cc]omponents/
-
-# MSTest test Results
-[Tt]est[Rr]esult*/
-[Bb]uild[Ll]og.*
-
-*_i.c
-*_p.c
-*.ilk
-*.meta
-*.obj
-*.pch
-*.pdb
-*.pgc
-*.pgd
-*.rsp
-*.sbr
-*.tlb
-*.tli
-*.tlh
-*.tmp
-*.tmp_proj
-*.log
-*.vspscc
-*.vssscc
-.builds
-*.pidb
-*.log
-*.scc
-
-# Visual C++ cache files
-ipch/
-*.aps
-*.ncb
-*.opensdf
-*.sdf
-*.cachefile
-
-# Visual Studio profiler
-*.psess
-*.vsp
-*.vspx
-
-# Guidance Automation Toolkit
-*.gpState
-
-# ReSharper is a .NET coding add-in
-_ReSharper*/
-*.[Rr]e[Ss]harper
-
-# TeamCity is a build add-in
-_TeamCity*
-
-# DotCover is a Code Coverage Tool
-*.dotCover
-
-# NCrunch
-*.ncrunch*
-.*crunch*.local.xml
-
-# Installshield output folder
-[Ee]xpress/
-
-# DocProject is a documentation generator add-in
-DocProject/buildhelp/
-DocProject/Help/*.HxT
-DocProject/Help/*.HxC
-DocProject/Help/*.hhc
-DocProject/Help/*.hhk
-DocProject/Help/*.hhp
-DocProject/Help/Html2
-DocProject/Help/html
-
-# Click-Once directory
-publish/
-
-# Publish Web Output
-*.Publish.xml
-*.pubxml
-
-# NuGet Packages Directory
-## TODO: If you have NuGet Package Restore enabled, uncomment the next line
-#packages/
-
-# Windows Azure Build Output
-csx
-*.build.csdef
-
-# Windows Store app package directory
-AppPackages/
-
-# Others
-sql/
-*.Cache
-ClientBin/
-[Ss]tyle[Cc]op.*
-~$*
-*~
-*.dbmdl
-*.[Pp]ublish.xml
-*.pfx
-*.publishsettings
-
-# RIA/Silverlight projects
-Generated_Code/
-
-# Backup & report files from converting an old project file to a newer
-# Visual Studio version. Backup files are not needed, because we have git ;-)
-_UpgradeReport_Files/
-Backup*/
-UpgradeLog*.XML
-UpgradeLog*.htm
-
-# SQL Server files
-App_Data/*.mdf
-App_Data/*.ldf
-
-#############
-## Windows detritus
-#############
-
-# Windows image file caches
-Thumbs.db
-ehthumbs.db
-
-# Folder config file
-Desktop.ini
-
-# Recycle Bin used on file shares
-$RECYCLE.BIN/
-
-# Mac crap
-.DS_Store
-
-
-#############
-## Python
-#############
-
-*.py[co]
-
-# Packages
-*.egg
-*.egg-info
-dist/
-build/
-eggs/
-parts/
-var/
-sdist/
-develop-eggs/
-.installed.cfg
-
-# Installer logs
-pip-log.txt
-
-# Unit test / coverage reports
-.coverage
-.tox
-
-#Translations
-*.mo
-
-#Mr Developer
-.mr.developer.cfg

+ 0 - 6
Demos/TripExpenses/.nuget/NuGet.Config

@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<configuration>
-  <solution>
-    <add key="disableSourceControlIntegration" value="true" />
-  </solution>
-</configuration>

BIN
Demos/TripExpenses/.nuget/NuGet.exe


+ 0 - 144
Demos/TripExpenses/.nuget/NuGet.targets

@@ -1,144 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-    <PropertyGroup>
-        <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">$(MSBuildProjectDirectory)\..\</SolutionDir>
-
-        <!-- Enable the restore command to run before builds -->
-        <RestorePackages Condition="  '$(RestorePackages)' == '' ">false</RestorePackages>
-
-        <!-- Property that enables building a package from a project -->
-        <BuildPackage Condition=" '$(BuildPackage)' == '' ">false</BuildPackage>
-
-        <!-- Determines if package restore consent is required to restore packages -->
-        <RequireRestoreConsent Condition=" '$(RequireRestoreConsent)' != 'false' ">true</RequireRestoreConsent>
-
-        <!-- Download NuGet.exe if it does not already exist -->
-        <DownloadNuGetExe Condition=" '$(DownloadNuGetExe)' == '' ">false</DownloadNuGetExe>
-    </PropertyGroup>
-
-    <ItemGroup Condition=" '$(PackageSources)' == '' ">
-        <!-- Package sources used to restore packages. By default, registered sources under %APPDATA%\NuGet\NuGet.Config will be used -->
-        <!-- The official NuGet package source (https://www.nuget.org/api/v2/) will be excluded if package sources are specified and it does not appear in the list -->
-        <!--
-            <PackageSource Include="https://www.nuget.org/api/v2/" />
-            <PackageSource Include="https://my-nuget-source/nuget/" />
-        -->
-    </ItemGroup>
-
-    <PropertyGroup Condition=" '$(OS)' == 'Windows_NT'">
-        <!-- Windows specific commands -->
-        <NuGetToolsPath>$([System.IO.Path]::Combine($(SolutionDir), ".nuget"))</NuGetToolsPath>
-    </PropertyGroup>
-
-    <PropertyGroup Condition=" '$(OS)' != 'Windows_NT'">
-        <!-- We need to launch nuget.exe with the mono command if we're not on windows -->
-        <NuGetToolsPath>$(SolutionDir).nuget</NuGetToolsPath>
-    </PropertyGroup>
-
-    <PropertyGroup>
-        <PackagesProjectConfig Condition=" '$(OS)' == 'Windows_NT'">$(MSBuildProjectDirectory)\packages.$(MSBuildProjectName.Replace(' ', '_')).config</PackagesProjectConfig>
-        <PackagesProjectConfig Condition=" '$(OS)' != 'Windows_NT'">$(MSBuildProjectDirectory)\packages.$(MSBuildProjectName).config</PackagesProjectConfig>
-    </PropertyGroup>
-
-    <PropertyGroup>
-      <PackagesConfig Condition="Exists('$(MSBuildProjectDirectory)\packages.config')">$(MSBuildProjectDirectory)\packages.config</PackagesConfig>
-      <PackagesConfig Condition="Exists('$(PackagesProjectConfig)')">$(PackagesProjectConfig)</PackagesConfig>
-    </PropertyGroup>
-    
-    <PropertyGroup>
-        <!-- NuGet command -->
-        <NuGetExePath Condition=" '$(NuGetExePath)' == '' ">$(NuGetToolsPath)\NuGet.exe</NuGetExePath>
-        <PackageSources Condition=" $(PackageSources) == '' ">@(PackageSource)</PackageSources>
-
-        <NuGetCommand Condition=" '$(OS)' == 'Windows_NT'">"$(NuGetExePath)"</NuGetCommand>
-        <NuGetCommand Condition=" '$(OS)' != 'Windows_NT' ">mono --runtime=v4.0.30319 "$(NuGetExePath)"</NuGetCommand>
-
-        <PackageOutputDir Condition="$(PackageOutputDir) == ''">$(TargetDir.Trim('\\'))</PackageOutputDir>
-
-        <RequireConsentSwitch Condition=" $(RequireRestoreConsent) == 'true' ">-RequireConsent</RequireConsentSwitch>
-        <NonInteractiveSwitch Condition=" '$(VisualStudioVersion)' != '' AND '$(OS)' == 'Windows_NT' ">-NonInteractive</NonInteractiveSwitch>
-
-        <PaddedSolutionDir Condition=" '$(OS)' == 'Windows_NT'">"$(SolutionDir) "</PaddedSolutionDir>
-        <PaddedSolutionDir Condition=" '$(OS)' != 'Windows_NT' ">"$(SolutionDir)"</PaddedSolutionDir>
-
-        <!-- Commands -->
-        <RestoreCommand>$(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)"  $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir $(PaddedSolutionDir)</RestoreCommand>
-        <BuildCommand>$(NuGetCommand) pack "$(ProjectPath)" -Properties "Configuration=$(Configuration);Platform=$(Platform)" $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols</BuildCommand>
-
-        <!-- We need to ensure packages are restored prior to assembly resolve -->
-        <BuildDependsOn Condition="$(RestorePackages) == 'true'">
-            RestorePackages;
-            $(BuildDependsOn);
-        </BuildDependsOn>
-
-        <!-- Make the build depend on restore packages -->
-        <BuildDependsOn Condition="$(BuildPackage) == 'true'">
-            $(BuildDependsOn);
-            BuildPackage;
-        </BuildDependsOn>
-    </PropertyGroup>
-
-    <Target Name="CheckPrerequisites">
-        <!-- Raise an error if we're unable to locate nuget.exe  -->
-        <Error Condition="'$(DownloadNuGetExe)' != 'true' AND !Exists('$(NuGetExePath)')" Text="Unable to locate '$(NuGetExePath)'" />
-        <!--
-        Take advantage of MsBuild's build dependency tracking to make sure that we only ever download nuget.exe once.
-        This effectively acts as a lock that makes sure that the download operation will only happen once and all
-        parallel builds will have to wait for it to complete.
-        -->
-        <MsBuild Targets="_DownloadNuGet" Projects="$(MSBuildThisFileFullPath)" Properties="Configuration=NOT_IMPORTANT;DownloadNuGetExe=$(DownloadNuGetExe)" />
-    </Target>
-
-    <Target Name="_DownloadNuGet">
-        <DownloadNuGet OutputFilename="$(NuGetExePath)" Condition=" '$(DownloadNuGetExe)' == 'true' AND !Exists('$(NuGetExePath)')" />
-    </Target>
-
-    <Target Name="RestorePackages" DependsOnTargets="CheckPrerequisites">        
-        <Exec Command="$(RestoreCommand)"
-              Condition="'$(OS)' != 'Windows_NT' And Exists('$(PackagesConfig)')" />
-
-        <Exec Command="$(RestoreCommand)"
-              LogStandardErrorAsError="true"
-              Condition="'$(OS)' == 'Windows_NT' And Exists('$(PackagesConfig)')" />
-    </Target>
-
-    <Target Name="BuildPackage" DependsOnTargets="CheckPrerequisites">
-        <Exec Command="$(BuildCommand)"
-              Condition=" '$(OS)' != 'Windows_NT' " />
-
-        <Exec Command="$(BuildCommand)"
-              LogStandardErrorAsError="true"
-              Condition=" '$(OS)' == 'Windows_NT' " />
-    </Target>
-
-    <UsingTask TaskName="DownloadNuGet" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
-        <ParameterGroup>
-            <OutputFilename ParameterType="System.String" Required="true" />
-        </ParameterGroup>
-        <Task>
-            <Reference Include="System.Core" />
-            <Using Namespace="System" />
-            <Using Namespace="System.IO" />
-            <Using Namespace="System.Net" />
-            <Using Namespace="Microsoft.Build.Framework" />
-            <Using Namespace="Microsoft.Build.Utilities" />
-            <Code Type="Fragment" Language="cs">
-                <![CDATA[
-                try {
-                    OutputFilename = Path.GetFullPath(OutputFilename);
-
-                    Log.LogMessage("Downloading latest version of NuGet.exe...");
-                    WebClient webClient = new WebClient();
-                    webClient.DownloadFile("https://www.nuget.org/nuget.exe", OutputFilename);
-
-                    return true;
-                }
-                catch (Exception ex) {
-                    Log.LogErrorFromException(ex);
-                    return false;
-                }
-            ]]>
-            </Code>
-        </Task>
-    </UsingTask>
-</Project>

+ 6 - 2
Demos/TripExpenses/README.md

@@ -1,13 +1,17 @@
-Xamarin.Forms-TripExpenses-TechEd
+Xamarin.Forms-TripExpenses
 ==========================
 
 Xamarin.Forms Azure Demo of a simple expense app with Azure Mobile Services online and offline sync with a backed SQLite database for iOS, Android, and Windows Phone.
 
 ##Setup
 
+* By default TripExpenses uses a cross-platform Json Based file system, however you can add Azure Mobile Services easily by following:
+
 * Signup for an Azure Mobile Services account: http://azure.microsoft.com/en-us/services/mobile-services/
+* Open: XMLDataStore.cs and comment OUT the [assemby:Dependency()] flag
 * Create a new Azure Mobile Services Table Called "TripExpense"
-* Open "DataStore.cs" in TripExpenses shared project
+* Open “AzureDataStore.cs" in TripExpenses shared project
+* Comment IN the [assemby:Dependency()] flag
 * Edit: MobileService = new MobileServiceClient(
         "https://"+"PUT-SITE-HERE" +".azure-mobile.net/",
         "PUT-YOUR-API-KEY-HERE");

+ 25 - 0
Demos/TripExpenses/TripExpenses.UI/Converters/MultiTriggerConverter.cs

@@ -0,0 +1,25 @@
+using System;
+using Xamarin.Forms;
+using System.Globalization;
+
+namespace TripExpenses.UI
+{
+	public class MultiTriggerConverter : IValueConverter
+	{
+		public object Convert(object value, Type targetType,
+			object parameter, CultureInfo culture)
+		{
+			if ((int)value > 0) // length > 0 ?
+				return true;            // some data has been entered
+			else
+				return false;           // input is empty
+		}
+
+		public object ConvertBack(object value, Type targetType,
+			object parameter, CultureInfo culture)
+		{
+			throw new NotSupportedException ();
+		}
+	}
+}
+

+ 12 - 0
Demos/TripExpenses/TripExpenses.UI/MyClass.cs

@@ -0,0 +1,12 @@
+using System;
+
+namespace TripExpenses.UI
+{
+	public class MyClass
+	{
+		public MyClass ()
+		{
+		}
+	}
+}
+

+ 27 - 0
Demos/TripExpenses/TripExpenses.UI/Properties/AssemblyInfo.cs

@@ -0,0 +1,27 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+// Information about this assembly is defined by the following attributes.
+// Change them to the values specific to your project.
+
+[assembly: AssemblyTitle ("TripExpenses.UI")]
+[assembly: AssemblyDescription ("")]
+[assembly: AssemblyConfiguration ("")]
+[assembly: AssemblyCompany ("")]
+[assembly: AssemblyProduct ("")]
+[assembly: AssemblyCopyright ("jamesmontemagno")]
+[assembly: AssemblyTrademark ("")]
+[assembly: AssemblyCulture ("")]
+
+// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
+// The form "{Major}.{Minor}.*" will automatically update the build and revision,
+// and "{Major}.{Minor}.{Build}.*" will update just the revision.
+
+[assembly: AssemblyVersion ("1.0.*")]
+
+// The following attributes are used to specify the signing key for the assembly,
+// if desired. See the Mono documentation for more information about signing.
+
+//[assembly: AssemblyDelaySign(false)]
+//[assembly: AssemblyKeyFile("")]
+

+ 62 - 0
Demos/TripExpenses/TripExpenses.UI/TripExpenses.UI.csproj

@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <ProjectGuid>{E1DF5355-B3F1-4991-A022-897C33DD29DB}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <RootNamespace>TripExpenses.UI</RootNamespace>
+    <AssemblyName>TripExpenses.UI</AssemblyName>
+    <TargetFrameworkProfile>Profile78</TargetFrameworkProfile>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
+    <RestorePackages>true</RestorePackages>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug</OutputPath>
+    <DefineConstants>DEBUG;</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>false</ConsolePause>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>full</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>false</ConsolePause>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Converters\MultiTriggerConverter.cs" />
+  </ItemGroup>
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
+  <Import Project="..\packages\Xamarin.Forms.1.4.2.6359\build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Xamarin.Forms.targets" Condition="Exists('..\packages\Xamarin.Forms.1.4.2.6359\build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Xamarin.Forms.targets')" />
+  <ItemGroup />
+  <ItemGroup>
+    <Reference Include="Xamarin.Forms.Core">
+      <HintPath>..\packages\Xamarin.Forms.1.4.2.6359\lib\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Xamarin.Forms.Core.dll</HintPath>
+    </Reference>
+    <Reference Include="Xamarin.Forms.Xaml">
+      <HintPath>..\packages\Xamarin.Forms.1.4.2.6359\lib\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Xamarin.Forms.Xaml.dll</HintPath>
+    </Reference>
+    <Reference Include="Xamarin.Forms.Platform">
+      <HintPath>..\packages\Xamarin.Forms.1.4.2.6359\lib\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Xamarin.Forms.Platform.dll</HintPath>
+    </Reference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
+  </Target>
+</Project>

+ 4 - 0
Demos/TripExpenses/TripExpenses.UI/packages.config

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="Xamarin.Forms" version="1.4.2.6359" targetFramework="portable-net45+win+wp80+MonoTouch10+MonoAndroid10+xamarinmac20+xamarinios10" />
+</packages>

+ 129 - 56
Demos/TripExpenses/TripExpenses.sln

@@ -1,15 +1,9 @@
 
 Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 2013
-VisualStudioVersion = 12.0.30501.0
+# Visual Studio 2012
+VisualStudioVersion = 12.0.31101.0
 MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TripExpenses.WinPhone", "TripExpenses\TripExpenses.WinPhone\TripExpenses.WinPhone.csproj", "{76F43AAB-2104-4A36-95B0-10C8390D01A6}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TripExpenses.iOS", "TripExpenses\TripExpenses.iOS\TripExpenses.iOS.csproj", "{D6028D44-6FAD-4A97-A934-90435BAB207A}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TripExpenses.Android", "TripExpenses\TripExpenses.Android\TripExpenses.Android.csproj", "{5FDE5A98-2438-421B-8A34-DAEC90C549EA}"
-EndProject
-Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "TripExpenses", "TripExpenses\TripExpenses\TripExpenses.shproj", "{908B9AB7-C998-4B59-B85E-EC37794FB92B}"
+Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "TripExpenses.Shared", "TripExpenses\TripExpenses\TripExpenses.Shared.shproj", "{908B9AB7-C998-4B59-B85E-EC37794FB92B}"
 EndProject
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{08A004CC-1F41-4F11-9F6E-3A3339642151}"
 	ProjectSection(SolutionItems) = preProject
@@ -18,13 +12,17 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{08A004
 		.nuget\NuGet.targets = .nuget\NuGet.targets
 	EndProjectSection
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TripExpenses.UI", "TripExpenses.UI\TripExpenses.UI.csproj", "{E1DF5355-B3F1-4991-A022-897C33DD29DB}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Platforms", "Platforms", "{585B80C2-8D3B-4AE6-AE23-F26FC3A93F9F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TripExpenses.Android", "TripExpenses\TripExpenses.Android\TripExpenses.Android.csproj", "{5FDE5A98-2438-421B-8A34-DAEC90C549EA}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TripExpenses.iOS", "TripExpenses\TripExpenses.iOS\TripExpenses.iOS.csproj", "{D6028D44-6FAD-4A97-A934-90435BAB207A}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TripExpenses.WinPhone", "TripExpenses\TripExpenses.WinPhone\TripExpenses.WinPhone.csproj", "{76F43AAB-2104-4A36-95B0-10C8390D01A6}"
+EndProject
 Global
-	GlobalSection(SharedMSBuildProjectFiles) = preSolution
-		TripExpenses\TripExpenses\TripExpenses.projitems*{5fde5a98-2438-421b-8a34-daec90c549ea}*SharedItemsImports = 4
-		TripExpenses\TripExpenses\TripExpenses.projitems*{908b9ab7-c998-4b59-b85e-ec37794fb92b}*SharedItemsImports = 13
-		TripExpenses\TripExpenses\TripExpenses.projitems*{d6028d44-6fad-4a97-a934-90435bab207a}*SharedItemsImports = 4
-		TripExpenses\TripExpenses\TripExpenses.projitems*{76f43aab-2104-4a36-95b0-10c8390d01a6}*SharedItemsImports = 4
-	EndGlobalSection
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Ad-Hoc|Any CPU = Ad-Hoc|Any CPU
 		Ad-Hoc|ARM = Ad-Hoc|ARM
@@ -52,6 +50,46 @@ Global
 		Release|x86 = Release|x86
 	EndGlobalSection
 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
+		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
+		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Ad-Hoc|Any CPU.Deploy.0 = Release|Any CPU
+		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Ad-Hoc|ARM.ActiveCfg = Release|Any CPU
+		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
+		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Ad-Hoc|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Ad-Hoc|Mixed Platforms.Build.0 = Release|Any CPU
+		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Ad-Hoc|Mixed Platforms.Deploy.0 = Release|Any CPU
+		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU
+		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
+		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.AppStore|Any CPU.Build.0 = Release|Any CPU
+		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.AppStore|Any CPU.Deploy.0 = Release|Any CPU
+		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.AppStore|ARM.ActiveCfg = Release|Any CPU
+		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.AppStore|iPhone.ActiveCfg = Release|Any CPU
+		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.AppStore|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.AppStore|Mixed Platforms.Build.0 = Release|Any CPU
+		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.AppStore|Mixed Platforms.Deploy.0 = Release|Any CPU
+		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.AppStore|x86.ActiveCfg = Release|Any CPU
+		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
+		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Debug|ARM.ActiveCfg = Debug|Any CPU
+		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Debug|Mixed Platforms.Deploy.0 = Debug|Any CPU
+		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Release|Any CPU.Build.0 = Release|Any CPU
+		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Release|Any CPU.Deploy.0 = Release|Any CPU
+		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Release|ARM.ActiveCfg = Release|Any CPU
+		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Release|iPhone.ActiveCfg = Release|Any CPU
+		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Release|Mixed Platforms.Deploy.0 = Release|Any CPU
+		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Release|x86.ActiveCfg = Release|Any CPU
 		{76F43AAB-2104-4A36-95B0-10C8390D01A6}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
 		{76F43AAB-2104-4A36-95B0-10C8390D01A6}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
 		{76F43AAB-2104-4A36-95B0-10C8390D01A6}.Ad-Hoc|Any CPU.Deploy.0 = Release|Any CPU
@@ -132,7 +170,8 @@ Global
 		{D6028D44-6FAD-4A97-A934-90435BAB207A}.AppStore|Mixed Platforms.Build.0 = AppStore|iPhone
 		{D6028D44-6FAD-4A97-A934-90435BAB207A}.AppStore|Mixed Platforms.Deploy.0 = AppStore|iPhone
 		{D6028D44-6FAD-4A97-A934-90435BAB207A}.AppStore|x86.ActiveCfg = AppStore|iPhone
-		{D6028D44-6FAD-4A97-A934-90435BAB207A}.Debug|Any CPU.ActiveCfg = Debug|iPhone
+		{D6028D44-6FAD-4A97-A934-90435BAB207A}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator
+		{D6028D44-6FAD-4A97-A934-90435BAB207A}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator
 		{D6028D44-6FAD-4A97-A934-90435BAB207A}.Debug|ARM.ActiveCfg = Debug|iPhone
 		{D6028D44-6FAD-4A97-A934-90435BAB207A}.Debug|iPhone.ActiveCfg = Debug|iPhone
 		{D6028D44-6FAD-4A97-A934-90435BAB207A}.Debug|iPhone.Build.0 = Debug|iPhone
@@ -156,46 +195,80 @@ Global
 		{D6028D44-6FAD-4A97-A934-90435BAB207A}.Release|Mixed Platforms.Build.0 = Release|iPhone
 		{D6028D44-6FAD-4A97-A934-90435BAB207A}.Release|Mixed Platforms.Deploy.0 = Release|iPhone
 		{D6028D44-6FAD-4A97-A934-90435BAB207A}.Release|x86.ActiveCfg = Release|iPhone
-		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
-		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
-		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Ad-Hoc|Any CPU.Deploy.0 = Release|Any CPU
-		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Ad-Hoc|ARM.ActiveCfg = Release|Any CPU
-		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
-		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
-		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Ad-Hoc|Mixed Platforms.ActiveCfg = Release|Any CPU
-		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Ad-Hoc|Mixed Platforms.Build.0 = Release|Any CPU
-		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Ad-Hoc|Mixed Platforms.Deploy.0 = Release|Any CPU
-		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU
-		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
-		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.AppStore|Any CPU.Build.0 = Release|Any CPU
-		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.AppStore|Any CPU.Deploy.0 = Release|Any CPU
-		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.AppStore|ARM.ActiveCfg = Release|Any CPU
-		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.AppStore|iPhone.ActiveCfg = Release|Any CPU
-		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
-		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.AppStore|Mixed Platforms.ActiveCfg = Release|Any CPU
-		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.AppStore|Mixed Platforms.Build.0 = Release|Any CPU
-		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.AppStore|Mixed Platforms.Deploy.0 = Release|Any CPU
-		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.AppStore|x86.ActiveCfg = Release|Any CPU
-		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
-		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Debug|ARM.ActiveCfg = Debug|Any CPU
-		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Debug|iPhone.ActiveCfg = Debug|Any CPU
-		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
-		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
-		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
-		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Debug|Mixed Platforms.Deploy.0 = Debug|Any CPU
-		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Debug|x86.ActiveCfg = Debug|Any CPU
-		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Release|Any CPU.Build.0 = Release|Any CPU
-		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Release|Any CPU.Deploy.0 = Release|Any CPU
-		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Release|ARM.ActiveCfg = Release|Any CPU
-		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Release|iPhone.ActiveCfg = Release|Any CPU
-		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
-		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
-		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Release|Mixed Platforms.Build.0 = Release|Any CPU
-		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Release|Mixed Platforms.Deploy.0 = Release|Any CPU
-		{5FDE5A98-2438-421B-8A34-DAEC90C549EA}.Release|x86.ActiveCfg = Release|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.Ad-Hoc|ARM.ActiveCfg = Release|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.Ad-Hoc|ARM.Build.0 = Release|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.Ad-Hoc|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.Ad-Hoc|Mixed Platforms.Build.0 = Release|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.Ad-Hoc|x86.Build.0 = Release|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.AppStore|Any CPU.Build.0 = Release|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.AppStore|ARM.ActiveCfg = Release|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.AppStore|ARM.Build.0 = Release|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.AppStore|iPhone.ActiveCfg = Release|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.AppStore|iPhone.Build.0 = Release|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.AppStore|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.AppStore|Mixed Platforms.Build.0 = Release|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.AppStore|x86.ActiveCfg = Release|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.AppStore|x86.Build.0 = Release|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.Debug|ARM.ActiveCfg = Debug|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.Debug|ARM.Build.0 = Debug|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.Debug|iPhone.Build.0 = Debug|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.Debug|x86.Build.0 = Debug|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.Release|Any CPU.Build.0 = Release|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.Release|ARM.ActiveCfg = Release|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.Release|ARM.Build.0 = Release|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.Release|iPhone.ActiveCfg = Release|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.Release|iPhone.Build.0 = Release|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.Release|x86.ActiveCfg = Release|Any CPU
+		{E1DF5355-B3F1-4991-A022-897C33DD29DB}.Release|x86.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(NestedProjects) = preSolution
+		{5FDE5A98-2438-421B-8A34-DAEC90C549EA} = {585B80C2-8D3B-4AE6-AE23-F26FC3A93F9F}
+		{D6028D44-6FAD-4A97-A934-90435BAB207A} = {585B80C2-8D3B-4AE6-AE23-F26FC3A93F9F}
+		{76F43AAB-2104-4A36-95B0-10C8390D01A6} = {585B80C2-8D3B-4AE6-AE23-F26FC3A93F9F}
+	EndGlobalSection
+	GlobalSection(MonoDevelopProperties) = preSolution
+		Policies = $0
+		$0.TextStylePolicy = $1
+		$1.FileWidth = 120
+		$1.TabWidth = 2
+		$1.IndentWidth = 2
+		$1.inheritsSet = Mono
+		$1.inheritsScope = text/plain
+		$1.scope = text/x-csharp
+		$0.CSharpFormattingPolicy = $2
+		$2.AfterDelegateDeclarationParameterComma = True
+		$2.inheritsSet = Mono
+		$2.inheritsScope = text/x-csharp
+		$2.scope = text/x-csharp
+	EndGlobalSection
+	GlobalSection(SharedMSBuildProjectFiles) = preSolution
+		TripExpenses\TripExpenses\TripExpenses.Shared.projitems*{5fde5a98-2438-421b-8a34-daec90c549ea}*SharedItemsImports = 4
+		TripExpenses\TripExpenses\TripExpenses.Shared.projitems*{908b9ab7-c998-4b59-b85e-ec37794fb92b}*SharedItemsImports = 13
+		TripExpenses\TripExpenses\TripExpenses.Shared.projitems*{d6028d44-6fad-4a97-a934-90435bab207a}*SharedItemsImports = 4
+		TripExpenses\TripExpenses\TripExpenses.Shared.projitems*{76f43aab-2104-4a36-95b0-10c8390d01a6}*SharedItemsImports = 4
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE

+ 15 - 0
Demos/TripExpenses/TripExpenses.userprefs

@@ -0,0 +1,15 @@
+<Properties StartupItem="TripExpenses/TripExpenses.iOS/TripExpenses.iOS.csproj">
+  <MonoDevelop.Ide.Workspace ActiveConfiguration="Debug" PreferredExecutionTarget="Android.Nexus 4 (Lollipop)" />
+  <MonoDevelop.Ide.Workbench ActiveDocument="TripExpenses/TripExpenses/Views/ExpenseListPage.xaml">
+    <Files>
+      <File FileName="TripExpenses/TripExpenses/Services/AzureDataStore.cs" Line="1" Column="1" />
+      <File FileName="TripExpenses/TripExpenses/Services/XMLDataStore.cs" Line="1" Column="1" />
+      <File FileName="TripExpenses/TripExpenses/Views/ExpenseListPage.xaml" Line="22" Column="23" />
+      <File FileName="TripExpenses/TripExpenses/Views/DetailsPage.xaml" Line="1" Column="1" />
+    </Files>
+  </MonoDevelop.Ide.Workbench>
+  <MonoDevelop.Ide.DebuggingService.Breakpoints>
+    <BreakpointStore />
+  </MonoDevelop.Ide.DebuggingService.Breakpoints>
+  <MonoDevelop.Ide.DebuggingService.PinnedWatches />
+</Properties>

+ 5 - 1
Demos/TripExpenses/TripExpenses/TripExpenses.Android/Properties/AndroidManifest.xml

@@ -1,5 +1,9 @@
 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android">
 	<uses-sdk android:minSdkVersion="15" android:targetSdkVersion="21" />
-	<application android:theme="@android:style/Theme.Holo.Light"></application>
+	<application android:theme="@android:style/Theme.Holo.Light">
+	</application>
+	<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+	<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+	<uses-permission android:name="android.permission.INTERNET" />
 </manifest>

+ 19 - 12
Demos/TripExpenses/TripExpenses/TripExpenses.Android/Resources/Resource.Designer.cs

@@ -1,15 +1,15 @@
 #pragma warning disable 1591
-//------------------------------------------------------------------------------
-// <auto-generated>
-//     This code was generated by a tool.
-//     Runtime Version:4.0.30319.34014
-//
-//     Changes to this file may cause incorrect behavior and will be lost if
-//     the code is regenerated.
-// </auto-generated>
-//------------------------------------------------------------------------------
+// ------------------------------------------------------------------------------
+//  <autogenerated>
+//      This code was generated by a tool.
+//      Mono Runtime Version: 4.0.30319.17020
+// 
+//      Changes to this file may cause incorrect behavior and will be lost if 
+//      the code is regenerated.
+//  </autogenerated>
+// ------------------------------------------------------------------------------
 
-[assembly: global::Android.Runtime.ResourceDesignerAttribute("TripExpenses.Droid.Resource", IsApplication=true)]
+[assembly: Android.Runtime.ResourceDesignerAttribute("TripExpenses.Droid.Resource", IsApplication=true)]
 
 namespace TripExpenses.Droid
 {
@@ -28,6 +28,10 @@ namespace TripExpenses.Droid
 		{
 			global::Xamarin.Forms.Platform.Resource.String.ApplicationName = global::TripExpenses.Droid.Resource.String.ApplicationName;
 			global::Xamarin.Forms.Platform.Resource.String.Hello = global::TripExpenses.Droid.Resource.String.Hello;
+			global::PCLStorage.Resource.String.ApplicationName = global::TripExpenses.Droid.Resource.String.ApplicationName;
+			global::PCLStorage.Resource.String.Hello = global::TripExpenses.Droid.Resource.String.Hello;
+			global::Refractored.Xam.TTS.Resource.String.ApplicationName = global::TripExpenses.Droid.Resource.String.ApplicationName;
+			global::Refractored.Xam.TTS.Resource.String.Hello = global::TripExpenses.Droid.Resource.String.Hello;
 		}
 		
 		public partial class Attribute
@@ -47,10 +51,13 @@ namespace TripExpenses.Droid
 		{
 			
 			// aapt resource value: 0x7f020000
-			public const int Icon = 2130837504;
+			public const int add = 2130837504;
 			
 			// aapt resource value: 0x7f020001
-			public const int refresh = 2130837505;
+			public const int Icon = 2130837505;
+			
+			// aapt resource value: 0x7f020002
+			public const int refresh = 2130837506;
 			
 			static Drawable()
 			{

BIN
Demos/TripExpenses/TripExpenses/TripExpenses.Android/Resources/drawable-hdpi/add.png


BIN
Demos/TripExpenses/TripExpenses/TripExpenses.Android/Resources/drawable-mdpi/add.png


BIN
Demos/TripExpenses/TripExpenses/TripExpenses.Android/Resources/drawable-xhdpi/add.png


BIN
Demos/TripExpenses/TripExpenses/TripExpenses.Android/Resources/drawable-xxhdpi/add.png


+ 47 - 43
Demos/TripExpenses/TripExpenses/TripExpenses.Android/TripExpenses.Android.csproj

@@ -3,8 +3,6 @@
   <PropertyGroup>
     <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
-    <ProductVersion>8.0.30703</ProductVersion>
-    <SchemaVersion>2.0</SchemaVersion>
     <ProjectGuid>{5FDE5A98-2438-421B-8A34-DAEC90C549EA}</ProjectGuid>
     <ProjectTypeGuids>{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
     <OutputType>Library</OutputType>
@@ -21,9 +19,9 @@
     <AndroidSupportedAbis>armeabi,armeabi-v7a,x86</AndroidSupportedAbis>
     <AndroidStoreUncompressedFileExtensions />
     <MandroidI18n />
-    <JavaMaximumHeapSize />
+    <JavaMaximumHeapSize>
+    </JavaMaximumHeapSize>
     <JavaOptions />
-    <AndroidUseLatestPlatformSdk />
     <NuGetPackageImportStamp>8ecd6661</NuGetPackageImportStamp>
     <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
     <RestorePackages>true</RestorePackages>
@@ -36,7 +34,6 @@
     <DefineConstants>DEBUG;TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
-    <AndroidUseSharedRuntime>True</AndroidUseSharedRuntime>
     <AndroidLinkMode>None</AndroidLinkMode>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
@@ -47,71 +44,68 @@
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
     <AndroidUseSharedRuntime>False</AndroidUseSharedRuntime>
-    <AndroidLinkMode>SdkOnly</AndroidLinkMode>
   </PropertyGroup>
   <ItemGroup>
-    <Reference Include="FormsViewGroup, Version=1.4.0.0, Culture=neutral, processorArchitecture=MSIL">
+    <Reference Include="Mono.Android" />
+    <Reference Include="mscorlib" />
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Net.Http" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Xml" />
+    <Reference Include="FormsViewGroup, Version=1.4.0.0, Culture=neutral, PublicKeyToken=null">
       <HintPath>..\..\packages\Xamarin.Forms.1.4.2.6359\lib\MonoAndroid10\FormsViewGroup.dll</HintPath>
-      <Private>True</Private>
     </Reference>
-    <Reference Include="Microsoft.WindowsAzure.Mobile, Version=1.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+    <Reference Include="Microsoft.WindowsAzure.Mobile, Version=1.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
       <HintPath>..\..\packages\WindowsAzure.MobileServices.1.3.2\lib\monoandroid\Microsoft.WindowsAzure.Mobile.dll</HintPath>
-      <Private>True</Private>
     </Reference>
-    <Reference Include="Microsoft.WindowsAzure.Mobile.Ext, Version=1.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+    <Reference Include="Microsoft.WindowsAzure.Mobile.Ext, Version=1.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
       <HintPath>..\..\packages\WindowsAzure.MobileServices.1.3.2\lib\monoandroid\Microsoft.WindowsAzure.Mobile.Ext.dll</HintPath>
-      <Private>True</Private>
     </Reference>
-    <Reference Include="Microsoft.WindowsAzure.Mobile.SQLiteStore, Version=1.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+    <Reference Include="Microsoft.WindowsAzure.Mobile.SQLiteStore, Version=1.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
       <HintPath>..\..\packages\WindowsAzure.MobileServices.SQLiteStore.1.0.4\lib\portable-win+net45+wp8+wpa81+monotouch+monoandroid\Microsoft.WindowsAzure.Mobile.SQLiteStore.dll</HintPath>
-      <Private>True</Private>
     </Reference>
-    <Reference Include="Mono.Android" />
-    <Reference Include="mscorlib" />
-    <Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
+    <Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed">
       <HintPath>..\..\packages\Newtonsoft.Json.6.0.8\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll</HintPath>
-      <Private>True</Private>
     </Reference>
-    <Reference Include="SQLitePCL, Version=3.8.7.2, Culture=neutral, PublicKeyToken=bddade01e9c850c5, processorArchitecture=MSIL">
+    <Reference Include="SQLitePCL, Version=3.8.7.2, Culture=neutral, PublicKeyToken=bddade01e9c850c5">
       <HintPath>..\..\packages\SQLitePCL.3.8.7.2\lib\MonoAndroid\SQLitePCL.dll</HintPath>
-      <Private>True</Private>
     </Reference>
-    <Reference Include="SQLitePCL.Ext, Version=3.8.7.2, Culture=neutral, PublicKeyToken=bddade01e9c850c5, processorArchitecture=MSIL">
+    <Reference Include="SQLitePCL.Ext, Version=3.8.7.2, Culture=neutral, PublicKeyToken=bddade01e9c850c5">
       <HintPath>..\..\packages\SQLitePCL.3.8.7.2\lib\MonoAndroid\SQLitePCL.Ext.dll</HintPath>
-      <Private>True</Private>
     </Reference>
-    <Reference Include="System" />
-    <Reference Include="System.Core" />
-    <Reference Include="System.Net.Http" />
-    <Reference Include="System.Net.Http.Extensions, Version=2.2.29.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+    <Reference Include="System.Net.Http.Extensions, Version=2.2.29.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
       <HintPath>..\..\packages\Microsoft.Net.Http.2.2.29\lib\monoandroid\System.Net.Http.Extensions.dll</HintPath>
-      <Private>True</Private>
     </Reference>
-    <Reference Include="System.Net.Http.Primitives, Version=4.2.29.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+    <Reference Include="System.Net.Http.Primitives, Version=4.2.29.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
       <HintPath>..\..\packages\Microsoft.Net.Http.2.2.29\lib\monoandroid\System.Net.Http.Primitives.dll</HintPath>
-      <Private>True</Private>
     </Reference>
-    <Reference Include="System.Xml.Linq" />
-    <Reference Include="System.Xml" />
-    <Reference Include="Xamarin.Android.Support.v4, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+    <Reference Include="Xamarin.Android.Support.v4, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
       <HintPath>..\..\packages\Xamarin.Android.Support.v4.22.1.1.1\lib\MonoAndroid403\Xamarin.Android.Support.v4.dll</HintPath>
-      <Private>True</Private>
     </Reference>
-    <Reference Include="Xamarin.Forms.Core, Version=1.4.0.0, Culture=neutral, processorArchitecture=MSIL">
+    <Reference Include="Xamarin.Forms.Core, Version=1.4.0.0, Culture=neutral, PublicKeyToken=null">
       <HintPath>..\..\packages\Xamarin.Forms.1.4.2.6359\lib\MonoAndroid10\Xamarin.Forms.Core.dll</HintPath>
-      <Private>True</Private>
     </Reference>
-    <Reference Include="Xamarin.Forms.Platform, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+    <Reference Include="Xamarin.Forms.Platform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
       <HintPath>..\..\packages\Xamarin.Forms.1.4.2.6359\lib\MonoAndroid10\Xamarin.Forms.Platform.dll</HintPath>
-      <Private>True</Private>
     </Reference>
-    <Reference Include="Xamarin.Forms.Platform.Android, Version=1.4.0.0, Culture=neutral, processorArchitecture=MSIL">
+    <Reference Include="Xamarin.Forms.Platform.Android, Version=1.4.0.0, Culture=neutral, PublicKeyToken=null">
       <HintPath>..\..\packages\Xamarin.Forms.1.4.2.6359\lib\MonoAndroid10\Xamarin.Forms.Platform.Android.dll</HintPath>
-      <Private>True</Private>
     </Reference>
-    <Reference Include="Xamarin.Forms.Xaml, Version=1.4.0.0, Culture=neutral, processorArchitecture=MSIL">
+    <Reference Include="Xamarin.Forms.Xaml, Version=1.4.0.0, Culture=neutral, PublicKeyToken=null">
       <HintPath>..\..\packages\Xamarin.Forms.1.4.2.6359\lib\MonoAndroid10\Xamarin.Forms.Xaml.dll</HintPath>
-      <Private>True</Private>
+    </Reference>
+    <Reference Include="PCLStorage">
+      <HintPath>..\..\packages\PCLStorage.1.0.2\lib\monoandroid\PCLStorage.dll</HintPath>
+    </Reference>
+    <Reference Include="PCLStorage.Abstractions">
+      <HintPath>..\..\packages\PCLStorage.1.0.2\lib\monoandroid\PCLStorage.Abstractions.dll</HintPath>
+    </Reference>
+    <Reference Include="Refractored.Xam.TTS.Abstractions">
+      <HintPath>..\..\packages\Xam.Plugins.TextToSpeech.1.0.1\lib\MonoAndroid10\Refractored.Xam.TTS.Abstractions.dll</HintPath>
+    </Reference>
+    <Reference Include="Refractored.Xam.TTS">
+      <HintPath>..\..\packages\Xam.Plugins.TextToSpeech.1.0.1\lib\MonoAndroid10\Refractored.Xam.TTS.dll</HintPath>
     </Reference>
   </ItemGroup>
   <ItemGroup>
@@ -127,6 +121,10 @@
   </ItemGroup>
   <ItemGroup>
     <AndroidResource Include="Resources\Drawable\Icon.png" />
+    <AndroidResource Include="Resources\drawable-hdpi\add.png" />
+    <AndroidResource Include="Resources\drawable-mdpi\add.png" />
+    <AndroidResource Include="Resources\drawable-xhdpi\add.png" />
+    <AndroidResource Include="Resources\drawable-xxhdpi\add.png" />
   </ItemGroup>
   <ItemGroup>
     <Content Include="Properties\AndroidManifest.xml" />
@@ -135,8 +133,8 @@
     <AndroidResource Include="Resources\drawable-hdpi\refresh.png" />
     <AndroidResource Include="Resources\drawable-mdpi\refresh.png" />
   </ItemGroup>
-  <Import Project="..\TripExpenses\TripExpenses.projitems" Label="Shared" Condition="Exists('..\TripExpenses\TripExpenses.projitems')" />
-  <Import Project="..\TripExpenses\TripExpenses.projitems" Label="Shared" Condition="Exists('..\TripExpenses\TripExpenses.projitems')" />
+  <Import Project="..\TripExpenses\TripExpenses.Shared.projitems" Label="Shared" Condition="Exists('..\TripExpenses\TripExpenses.Shared.projitems')" />
+  <Import Project="..\TripExpenses\TripExpenses.Shared.projitems" Label="Shared" Condition="Exists('..\TripExpenses\TripExpenses.Shared.projitems')" />
   <Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
   <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
     <PropertyGroup>
@@ -156,4 +154,10 @@
   <Target Name="AfterBuild">
   </Target>
   -->
+  <ItemGroup>
+    <ProjectReference Include="..\..\TripExpenses.UI\TripExpenses.UI.csproj">
+      <Project>{E1DF5355-B3F1-4991-A022-897C33DD29DB}</Project>
+      <Name>TripExpenses.UI</Name>
+    </ProjectReference>
+  </ItemGroup>
 </Project>

+ 2 - 0
Demos/TripExpenses/TripExpenses/TripExpenses.Android/packages.config

@@ -4,9 +4,11 @@
   <package id="Microsoft.Bcl.Build" version="1.0.21" targetFramework="MonoAndroid44" />
   <package id="Microsoft.Net.Http" version="2.2.29" targetFramework="MonoAndroid44" />
   <package id="Newtonsoft.Json" version="6.0.8" targetFramework="MonoAndroid44" />
+  <package id="PCLStorage" version="1.0.2" targetFramework="MonoAndroid50" />
   <package id="SQLitePCL" version="3.8.7.2" targetFramework="MonoAndroid44" />
   <package id="WindowsAzure.MobileServices" version="1.3.2" targetFramework="MonoAndroid44" />
   <package id="WindowsAzure.MobileServices.SQLiteStore" version="1.0.4" targetFramework="MonoAndroid44" />
+  <package id="Xam.Plugins.TextToSpeech" version="1.0.1" targetFramework="MonoAndroid50" />
   <package id="Xamarin.Android.Support.v4" version="22.1.1.1" targetFramework="MonoAndroid44" />
   <package id="Xamarin.Forms" version="1.4.2.6359" targetFramework="MonoAndroid44" />
 </packages>

+ 27 - 5
Demos/TripExpenses/TripExpenses/TripExpenses.WinPhone/TripExpenses.WinPhone.csproj

@@ -1,11 +1,9 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <Import Project="..\..\packages\SQLitePCL.3.8.7.2\build\wp8\SQLitePCL.props" Condition="Exists('..\..\packages\SQLitePCL.3.8.7.2\build\wp8\SQLitePCL.props')" />
   <PropertyGroup>
     <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
-    <ProductVersion>10.0.20506</ProductVersion>
-    <SchemaVersion>2.0</SchemaVersion>
     <ProjectGuid>{76F43AAB-2104-4A36-95B0-10C8390D01A6}</ProjectGuid>
     <ProjectTypeGuids>{C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
     <OutputType>Library</OutputType>
@@ -152,6 +150,7 @@
     <Content Include="Toolkit.Content\ApplicationBar.Check.png" />
     <Content Include="Toolkit.Content\ApplicationBar.Delete.png" />
     <Content Include="Toolkit.Content\ApplicationBar.Select.png" />
+    <Content Include="add.png" />
   </ItemGroup>
   <ItemGroup>
     <EmbeddedResource Include="Resources\AppResources.resx">
@@ -183,6 +182,22 @@
       <HintPath>..\..\packages\Newtonsoft.Json.6.0.8\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll</HintPath>
       <Private>True</Private>
     </Reference>
+    <Reference Include="PCLStorage, Version=1.0.2.0, Culture=neutral, PublicKeyToken=286fe515a2c35b64, processorArchitecture=MSIL">
+      <HintPath>..\..\packages\PCLStorage.1.0.2\lib\wp8\PCLStorage.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="PCLStorage.Abstractions, Version=1.0.2.0, Culture=neutral, PublicKeyToken=286fe515a2c35b64, processorArchitecture=MSIL">
+      <HintPath>..\..\packages\PCLStorage.1.0.2\lib\wp8\PCLStorage.Abstractions.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="Refractored.Xam.TTS, Version=1.0.1.0, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\..\packages\Xam.Plugins.TextToSpeech.1.0.1\lib\wp8\Refractored.Xam.TTS.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="Refractored.Xam.TTS.Abstractions, Version=1.0.1.0, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\..\packages\Xam.Plugins.TextToSpeech.1.0.1\lib\wp8\Refractored.Xam.TTS.Abstractions.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
     <Reference Include="SQLitePCL, Version=3.8.7.2, Culture=neutral, PublicKeyToken=bddade01e9c850c5, processorArchitecture=MSIL">
       <HintPath>..\..\packages\SQLitePCL.3.8.7.2\lib\wp8\SQLitePCL.dll</HintPath>
       <Private>True</Private>
@@ -221,11 +236,18 @@
     </Reference>
   </ItemGroup>
   <ItemGroup>
+    <ProjectReference Include="..\..\TripExpenses.UI\TripExpenses.UI.csproj">
+      <Project>{e1df5355-b3f1-4991-a022-897c33dd29db}</Project>
+      <Name>TripExpenses.UI</Name>
+    </ProjectReference>
+  </ItemGroup>
+<ItemGroup>
     <SDKReference Include="SQLite.WP80, Version=3.8.7">
-      <Name>SQLite for Windows Phone %28SQLite.WP80, Version=3.8.7%29</Name>
+      <Name>SQLite for Windows Phone</Name>
     </SDKReference>
   </ItemGroup>
   <Import Project="..\TripExpenses\TripExpenses.projitems" Label="Shared" Condition="Exists('..\TripExpenses\TripExpenses.projitems')" />
+  <Import Project="..\TripExpenses\TripExpenses.Shared.projitems" Label="Shared" Condition="Exists('..\TripExpenses\TripExpenses.Shared.projitems')" />
   <Import Project="$(MSBuildExtensionsPath)\Microsoft\$(TargetFrameworkIdentifier)\$(TargetFrameworkVersion)\Microsoft.$(TargetFrameworkIdentifier).$(TargetFrameworkVersion).Overrides.targets" />
   <Import Project="$(MSBuildExtensionsPath)\Microsoft\$(TargetFrameworkIdentifier)\$(TargetFrameworkVersion)\Microsoft.$(TargetFrameworkIdentifier).CSharp.targets" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it.

BIN
Demos/TripExpenses/TripExpenses/TripExpenses.WinPhone/add.png


+ 2 - 0
Demos/TripExpenses/TripExpenses/TripExpenses.WinPhone/packages.config

@@ -4,9 +4,11 @@
   <package id="Microsoft.Bcl.Build" version="1.0.21" targetFramework="wp80" />
   <package id="Microsoft.Net.Http" version="2.2.29" targetFramework="wp80" />
   <package id="Newtonsoft.Json" version="6.0.8" targetFramework="wp80" />
+  <package id="PCLStorage" version="1.0.2" targetFramework="wp80" />
   <package id="SQLitePCL" version="3.8.7.2" targetFramework="wp80" />
   <package id="WindowsAzure.MobileServices" version="1.3.2" targetFramework="wp80" />
   <package id="WindowsAzure.MobileServices.SQLiteStore" version="1.0.4" targetFramework="wp80" />
   <package id="WPtoolkit" version="4.2013.08.16" targetFramework="wp80" />
+  <package id="Xam.Plugins.TextToSpeech" version="1.0.1" targetFramework="wp80" />
   <package id="Xamarin.Forms" version="1.4.2.6359" targetFramework="wp80" />
 </packages>

BIN
Demos/TripExpenses/TripExpenses/TripExpenses.iOS/Resources/add.png


BIN
Demos/TripExpenses/TripExpenses/TripExpenses.iOS/Resources/add@2x.png


BIN
Demos/TripExpenses/TripExpenses/TripExpenses.iOS/Resources/add@3x.png


+ 45 - 43
Demos/TripExpenses/TripExpenses/TripExpenses.iOS/TripExpenses.iOS.csproj

@@ -3,8 +3,6 @@
   <PropertyGroup>
     <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
     <Platform Condition=" '$(Platform)' == '' ">iPhoneSimulator</Platform>
-    <ProductVersion>8.0.30703</ProductVersion>
-    <SchemaVersion>2.0</SchemaVersion>
     <ProjectGuid>{D6028D44-6FAD-4A97-A934-90435BAB207A}</ProjectGuid>
     <ProjectTypeGuids>{FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
     <OutputType>Exe</OutputType>
@@ -26,18 +24,13 @@
     <ConsolePause>false</ConsolePause>
     <MtouchLink>None</MtouchLink>
     <MtouchDebug>True</MtouchDebug>
-    <MtouchSdkVersion>7.1</MtouchSdkVersion>
-    <MtouchProfiling>False</MtouchProfiling>
-    <MtouchExtraArgs />
-    <MtouchFastDev>False</MtouchFastDev>
-    <MtouchEnableGenericValueTypeSharing>True</MtouchEnableGenericValueTypeSharing>
-    <MtouchArch>Default, ARMv7</MtouchArch>
-    <MtouchUseLlvm>False</MtouchUseLlvm>
-    <MtouchUseThumb>False</MtouchUseThumb>
-    <MtouchUseSGen>False</MtouchUseSGen>
-    <MtouchUseRefCounting>False</MtouchUseRefCounting>
+    <MtouchSdkVersion>8.3</MtouchSdkVersion>
+    <MtouchArch>i386</MtouchArch>
     <MtouchOptimizePNGs>True</MtouchOptimizePNGs>
-    <MtouchI18n />
+    <MtouchI18n>
+    </MtouchI18n>
+    <CodesignKey>iPhone Developer</CodesignKey>
+    <MtouchUseRefCounting>true</MtouchUseRefCounting>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhoneSimulator' ">
     <DebugType>none</DebugType>
@@ -97,62 +90,65 @@
     <None Include="packages.config" />
   </ItemGroup>
   <ItemGroup>
-    <Reference Include="Microsoft.WindowsAzure.Mobile, Version=1.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+    <Reference Include="System" />
+    <Reference Include="System.Net.Http" />
+    <Reference Include="System.Xml" />
+    <Reference Include="System.Core" />
+    <Reference Include="Xamarin.iOS" />
+    <Reference Include="Microsoft.WindowsAzure.Mobile, Version=1.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
       <HintPath>..\..\packages\WindowsAzure.MobileServices.1.3.2\lib\Xamarin.iOS10\Microsoft.WindowsAzure.Mobile.dll</HintPath>
-      <Private>True</Private>
     </Reference>
-    <Reference Include="Microsoft.WindowsAzure.Mobile.Ext, Version=1.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+    <Reference Include="Microsoft.WindowsAzure.Mobile.Ext, Version=1.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
       <HintPath>..\..\packages\WindowsAzure.MobileServices.1.3.2\lib\Xamarin.iOS10\Microsoft.WindowsAzure.Mobile.Ext.dll</HintPath>
-      <Private>True</Private>
     </Reference>
-    <Reference Include="Microsoft.WindowsAzure.Mobile.SQLiteStore, Version=1.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+    <Reference Include="Microsoft.WindowsAzure.Mobile.SQLiteStore, Version=1.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
       <HintPath>..\..\packages\WindowsAzure.MobileServices.SQLiteStore.1.0.4\lib\portable-win+net45+wp8+wpa81+monotouch+monoandroid\Microsoft.WindowsAzure.Mobile.SQLiteStore.dll</HintPath>
-      <Private>True</Private>
     </Reference>
-    <Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
+    <Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed">
       <HintPath>..\..\packages\Newtonsoft.Json.6.0.8\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll</HintPath>
-      <Private>True</Private>
     </Reference>
-    <Reference Include="SQLitePCL, Version=3.8.7.2, Culture=neutral, PublicKeyToken=bddade01e9c850c5, processorArchitecture=MSIL">
+    <Reference Include="SQLitePCL, Version=3.8.7.2, Culture=neutral, PublicKeyToken=bddade01e9c850c5">
       <HintPath>..\..\packages\SQLitePCL.3.8.7.2\lib\Xamarin.iOS10\SQLitePCL.dll</HintPath>
-      <Private>True</Private>
     </Reference>
-    <Reference Include="SQLitePCL.Ext, Version=3.8.7.2, Culture=neutral, PublicKeyToken=bddade01e9c850c5, processorArchitecture=MSIL">
+    <Reference Include="SQLitePCL.Ext, Version=3.8.7.2, Culture=neutral, PublicKeyToken=bddade01e9c850c5">
       <HintPath>..\..\packages\SQLitePCL.3.8.7.2\lib\Xamarin.iOS10\SQLitePCL.Ext.dll</HintPath>
-      <Private>True</Private>
     </Reference>
-    <Reference Include="System" />
-    <Reference Include="System.Net.Http" />
-    <Reference Include="System.Net.Http.Extensions, Version=2.2.29.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+    <Reference Include="System.Net.Http.Extensions, Version=2.2.29.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
       <HintPath>..\..\packages\Microsoft.Net.Http.2.2.29\lib\Xamarin.iOS10\System.Net.Http.Extensions.dll</HintPath>
-      <Private>True</Private>
     </Reference>
-    <Reference Include="System.Net.Http.Primitives, Version=4.2.29.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+    <Reference Include="System.Net.Http.Primitives, Version=4.2.29.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
       <HintPath>..\..\packages\Microsoft.Net.Http.2.2.29\lib\Xamarin.iOS10\System.Net.Http.Primitives.dll</HintPath>
-      <Private>True</Private>
     </Reference>
-    <Reference Include="System.Xml" />
-    <Reference Include="System.Core" />
-    <Reference Include="Xamarin.Forms.Core, Version=1.4.0.0, Culture=neutral, processorArchitecture=MSIL">
+    <Reference Include="Xamarin.Forms.Core, Version=1.4.0.0, Culture=neutral, PublicKeyToken=null">
       <HintPath>..\..\packages\Xamarin.Forms.1.4.2.6359\lib\Xamarin.iOS10\Xamarin.Forms.Core.dll</HintPath>
-      <Private>True</Private>
     </Reference>
-    <Reference Include="Xamarin.Forms.Platform, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+    <Reference Include="Xamarin.Forms.Platform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
       <HintPath>..\..\packages\Xamarin.Forms.1.4.2.6359\lib\Xamarin.iOS10\Xamarin.Forms.Platform.dll</HintPath>
-      <Private>True</Private>
     </Reference>
-    <Reference Include="Xamarin.Forms.Platform.iOS, Version=1.4.0.0, Culture=neutral, processorArchitecture=MSIL">
+    <Reference Include="Xamarin.Forms.Platform.iOS, Version=1.4.0.0, Culture=neutral, PublicKeyToken=null">
       <HintPath>..\..\packages\Xamarin.Forms.1.4.2.6359\lib\Xamarin.iOS10\Xamarin.Forms.Platform.iOS.dll</HintPath>
-      <Private>True</Private>
     </Reference>
-    <Reference Include="Xamarin.Forms.Xaml, Version=1.4.0.0, Culture=neutral, processorArchitecture=MSIL">
+    <Reference Include="Xamarin.Forms.Xaml, Version=1.4.0.0, Culture=neutral, PublicKeyToken=null">
       <HintPath>..\..\packages\Xamarin.Forms.1.4.2.6359\lib\Xamarin.iOS10\Xamarin.Forms.Xaml.dll</HintPath>
-      <Private>True</Private>
     </Reference>
-    <Reference Include="Xamarin.iOS" />
+    <Reference Include="PCLStorage">
+      <HintPath>..\..\packages\PCLStorage.1.0.2\lib\portable-Xamarin.iOS+Xamarin.Mac\PCLStorage.dll</HintPath>
+    </Reference>
+    <Reference Include="PCLStorage.Abstractions">
+      <HintPath>..\..\packages\PCLStorage.1.0.2\lib\portable-Xamarin.iOS+Xamarin.Mac\PCLStorage.Abstractions.dll</HintPath>
+    </Reference>
+    <Reference Include="Refractored.Xam.TTS.Abstractions">
+      <HintPath>..\..\packages\Xam.Plugins.TextToSpeech.1.0.1\lib\Xamarin.iOS10\Refractored.Xam.TTS.Abstractions.dll</HintPath>
+    </Reference>
+    <Reference Include="Refractored.Xam.TTS">
+      <HintPath>..\..\packages\Xam.Plugins.TextToSpeech.1.0.1\lib\Xamarin.iOS10\Refractored.Xam.TTS.dll</HintPath>
+    </Reference>
   </ItemGroup>
   <ItemGroup>
     <BundleResource Include="Resources\Default-568h%402x.png" />
+    <BundleResource Include="Resources\add.png" />
+    <BundleResource Include="Resources\add%402x.png" />
+    <BundleResource Include="Resources\add%403x.png" />
   </ItemGroup>
   <ItemGroup>
     <BundleResource Include="Resources\refresh%402x.png" />
@@ -160,7 +156,7 @@
   <ItemGroup>
     <BundleResource Include="Resources\refresh.png" />
   </ItemGroup>
-  <Import Project="..\TripExpenses\TripExpenses.projitems" Label="Shared" Condition="Exists('..\TripExpenses\TripExpenses.projitems')" />
+  <Import Project="..\TripExpenses\TripExpenses.Shared.projitems" Label="Shared" Condition="Exists('..\TripExpenses\TripExpenses.Shared.projitems')" />
   <Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" />
   <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
     <PropertyGroup>
@@ -173,4 +169,10 @@
   <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
   <Import Project="..\..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets" Condition="Exists('..\..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" />
   <Import Project="..\..\packages\Xamarin.Forms.1.4.2.6359\build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Xamarin.Forms.targets" Condition="Exists('..\..\packages\Xamarin.Forms.1.4.2.6359\build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Xamarin.Forms.targets')" />
+  <ItemGroup>
+    <ProjectReference Include="..\..\TripExpenses.UI\TripExpenses.UI.csproj">
+      <Project>{E1DF5355-B3F1-4991-A022-897C33DD29DB}</Project>
+      <Name>TripExpenses.UI</Name>
+    </ProjectReference>
+  </ItemGroup>
 </Project>

+ 2 - 0
Demos/TripExpenses/TripExpenses/TripExpenses.iOS/packages.config

@@ -4,8 +4,10 @@
   <package id="Microsoft.Bcl.Build" version="1.0.21" targetFramework="xamarinios10" />
   <package id="Microsoft.Net.Http" version="2.2.29" targetFramework="xamarinios10" />
   <package id="Newtonsoft.Json" version="6.0.8" targetFramework="xamarinios10" />
+  <package id="PCLStorage" version="1.0.2" targetFramework="xamarinios10" />
   <package id="SQLitePCL" version="3.8.7.2" targetFramework="xamarinios10" />
   <package id="WindowsAzure.MobileServices" version="1.3.2" targetFramework="xamarinios10" />
   <package id="WindowsAzure.MobileServices.SQLiteStore" version="1.0.4" targetFramework="xamarinios10" />
+  <package id="Xam.Plugins.TextToSpeech" version="1.0.1" targetFramework="xamarinios10" />
   <package id="Xamarin.Forms" version="1.4.2.6359" targetFramework="xamarinios10" />
 </packages>

+ 18 - 0
Demos/TripExpenses/TripExpenses/TripExpenses/Interfaces/IDataStore.cs

@@ -0,0 +1,18 @@
+using System;
+using System.Threading.Tasks;
+using TripExpenses.Models;
+using System.Collections.Generic;
+
+namespace TripExpenses
+{
+	public interface IDataStore
+	{
+		Task Init();
+		Task<TripExpense> InsertExpenseAsync(TripExpense expense);
+		Task<TripExpense> UpdateExpenseAsync(TripExpense expense);
+		Task<IEnumerable<TripExpense>> GetExpensesAsync();
+		Task SyncExpensesAsync();
+		Task DeleteExpenseAsync(TripExpense expense);
+	}
+}
+

+ 11 - 1
Demos/TripExpenses/TripExpenses/TripExpenses/Models/TripExpense.cs

@@ -7,6 +7,10 @@ namespace TripExpenses.Models
 {
   public class TripExpense
   {
+		public TripExpense()
+		{
+		}
+
     [JsonProperty(PropertyName = "id")]
     public string Id { get; set; }
 
@@ -19,6 +23,12 @@ namespace TripExpenses.Models
     [Microsoft.WindowsAzure.MobileServices.Version]
     public string Version { get; set; }  
 
-
+		public void SyncProperties(TripExpense expense)
+		{
+			this.Billable = expense.Billable;
+			this.Category = expense.Category;
+			this.Name = expense.Name;
+			this.Price = expense.Price;
+		}
   }
 }

+ 27 - 13
Demos/TripExpenses/TripExpenses/TripExpenses/Services/DataStore.cs → Demos/TripExpenses/TripExpenses/TripExpenses/Services/AzureDataStore.cs

@@ -8,10 +8,15 @@ using Microsoft.WindowsAzure.MobileServices.SQLiteStore;
 using Microsoft.WindowsAzure.MobileServices.Sync;
 using System.Diagnostics;
 using System;
+using Xamarin.Forms;
+using TripExpenses.Services;
 
+//Comment back in to use azure
+
+//[assembly: Dependency(typeof(AzureDataStore))]
 namespace TripExpenses.Services
 {
-  public class DataStore
+  public class AzureDataStore : IDataStore
   {
     public List<TripExpense> Expenses { get; set; }
     public MobileServiceClient MobileService { get; set; }
@@ -19,7 +24,7 @@ namespace TripExpenses.Services
     private IMobileServiceSyncTable<TripExpense> expenseTable;
     private bool initialized = false;
 
-    public DataStore()
+    public AzureDataStore()
     {
 
       Expenses = new List<TripExpense>();
@@ -34,8 +39,8 @@ namespace TripExpenses.Services
 
       //comment back in to enable Azure Mobile Services.
       MobileService = new MobileServiceClient("https://" 
-		+ "PUT-SITE-HERE" + ".azure-mobile.net/",
-		"PUT-API-KEY-HERE");
+		+ "SITE-HERE" + ".azure-mobile.net/",
+				"API-KEY-HERE");
 
       
     }
@@ -52,30 +57,39 @@ namespace TripExpenses.Services
     }
 
 
-    public async Task InsertExpenseAsync(TripExpense expense)
+		public async Task<TripExpense> InsertExpenseAsync(TripExpense expense)
     {
       if (!initialized)
         await Init();
-      //expense.Id = (Expenses.Count + 1).ToString();
-      //Expenses.Add(expense);
+
       
       await expenseTable.InsertAsync(expense);
+			return expense;
     }
 
-    public async Task UpdateExpenseAsync(TripExpense expense)
+		public async Task<TripExpense> UpdateExpenseAsync(TripExpense expense)
     {
       if (!initialized)
         await Init();
       
       await expenseTable.UpdateAsync(expense);
+			return expense;
     }
 
+		public async Task DeleteExpenseAsync(TripExpense expense)
+		{
+			if (!initialized)
+				await Init();
+
+
+			await expenseTable.DeleteAsync(expense);
+		}
+
     public async Task<IEnumerable<TripExpense>> GetExpensesAsync()
     {
       if (!initialized)
         await Init();
 
-      //return Expenses;
       await SyncExpensesAsync();
       return await expenseTable.ToEnumerableAsync();
     }
@@ -85,7 +99,7 @@ namespace TripExpenses.Services
       try
       {
         await MobileService.SyncContext.PushAsync();
-		await expenseTable.PullAsync("allItems", expenseTable.CreateQuery());
+				await expenseTable.PullAsync("allItems", expenseTable.CreateQuery());
       }
       catch(Exception ex)
       {
@@ -95,15 +109,15 @@ namespace TripExpenses.Services
 
 
 
-    static readonly DataStore instance = new DataStore();
+    static readonly AzureDataStore instance = new AzureDataStore();
     /// <summary>
     /// Gets the instance of the Azure Web Service
     /// </summary>
-    public static DataStore Instance
+    public static AzureDataStore Instance
     {
       get
       {
-        return instance;
+		return instance;
       }
     }
 

+ 132 - 0
Demos/TripExpenses/TripExpenses/TripExpenses/Services/XMLDataStore.cs

@@ -0,0 +1,132 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Newtonsoft.Json;
+using System.Linq;
+using PCLStorage;
+using TripExpenses.Models;
+using Xamarin.Forms;
+using TripExpenses;
+
+//Comment out to use azure
+[assembly:Dependency(typeof(XmlDataStore))]
+namespace TripExpenses
+{
+	public class XmlDataStore : IDataStore
+	{
+
+		public XmlDataStore()
+		{
+		}
+
+
+		public static Task<T> DeserializeObjectAsync<T>(string value)
+		{
+			return Task.Factory.StartNew(() => JsonConvert.DeserializeObject<T>(value));
+		}
+
+		public static T DeserializeObject<T>(string value)
+		{
+			return JsonConvert.DeserializeObject<T>(value);
+		}
+
+		List<TripExpense> Expenses = new List<TripExpense>();
+
+		public Task<TripExpense> GetExpenseAsync(string id)
+		{
+			return Task.Run(()=>Expenses.FirstOrDefault(s => s.Id == id));
+		}
+
+		public async Task<IEnumerable<TripExpense>> GetExpensesAsync()
+		{
+			var rootFolder = FileSystem.Current.LocalStorage;
+
+			var folder = await rootFolder.CreateFolderAsync(Folder,
+				CreationCollisionOption.OpenIfExists);
+
+			var file = await folder.CreateFileAsync(File,
+				CreationCollisionOption.OpenIfExists);
+
+			var json = await file.ReadAllTextAsync();
+
+			if(!string.IsNullOrWhiteSpace(json))
+				Expenses = DeserializeObject<List<TripExpense>>(json);
+
+			if(Expenses.Count == 0)
+			{
+				var expense =  new TripExpense
+				{
+					Billable = true,
+					Category = "Transportation",
+					Name = "DevWeek 2015 Flight",
+					Price = "1000.00"
+				};
+				await SaveExpenseAsync(expense);
+			}
+
+			return Expenses;
+		}
+
+		public Task SyncExpensesAsync()
+		{
+			return Task.Run(() => { });
+		}
+
+		public async Task<TripExpense> InsertExpenseAsync(TripExpense expense)
+		{
+			return await SaveExpenseAsync (expense);
+		}
+
+		public async Task<TripExpense> UpdateExpenseAsync(TripExpense expense)
+		{
+			return await SaveExpenseAsync (expense);
+		}
+
+		public async Task<TripExpense> SaveExpenseAsync(TripExpense expense)
+		{
+			if(string.IsNullOrWhiteSpace(expense.Id))
+			{
+				expense.Id = DateTime.Now.ToString();
+				Expenses.Add(expense);
+			}
+			else
+			{
+				var found = Expenses.FirstOrDefault(e => e.Id == expense.Id);
+				if(found != null)
+					found.SyncProperties(expense);
+			}
+			await Save();
+			return expense;
+		}
+
+		public async Task DeleteExpenseAsync(TripExpense expense)
+		{
+			var id = expense.Id;
+			Expenses.Remove(expense);
+			await Save();
+		}
+
+		private string Folder = "Expenses";
+		private string File = "expenses.json";
+
+		private async Task Save()
+		{
+			var rootFolder = FileSystem.Current.LocalStorage;
+
+			var folder = await rootFolder.CreateFolderAsync(Folder,
+				CreationCollisionOption.OpenIfExists);
+
+			var file = await folder.CreateFileAsync(File,
+				CreationCollisionOption.ReplaceExisting);
+
+			await file.WriteAllTextAsync(JsonConvert.SerializeObject(Expenses));
+		}
+			
+
+		public Task Init()
+		{
+			return null;
+		}
+	}
+}
+

+ 6 - 3
Demos/TripExpenses/TripExpenses/TripExpenses/TripExpenses.projitems → Demos/TripExpenses/TripExpenses/TripExpenses/TripExpenses.Shared.projitems

@@ -11,10 +11,12 @@
   <ItemGroup>
     <Compile Include="$(MSBuildThisFileDirectory)App.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Models\TripExpense.cs" />
-    <Compile Include="$(MSBuildThisFileDirectory)Services\DataStore.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)ViewModels\BaseViewModel.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)ViewModels\DetailViewModel.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)ViewModels\ExpensesViewModel.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Interfaces\IDataStore.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Services\AzureDataStore.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Services\XMLDataStore.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Views\DetailsPage.xaml.cs">
       <DependentUpon>DetailsPage.xaml</DependentUpon>
       <SubType>Code</SubType>
@@ -24,13 +26,14 @@
       <SubType>Code</SubType>
     </Compile>
   </ItemGroup>
+  <ItemGroup>
+    <Folder Include="$(MSBuildThisFileDirectory)Interfaces\" />
+  </ItemGroup>
   <ItemGroup>
     <EmbeddedResource Include="$(MSBuildThisFileDirectory)Views\DetailsPage.xaml">
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>
     </EmbeddedResource>
-  </ItemGroup>
-  <ItemGroup>
     <EmbeddedResource Include="$(MSBuildThisFileDirectory)Views\ExpenseListPage.xaml">
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>

+ 2 - 2
Demos/TripExpenses/TripExpenses/TripExpenses/TripExpenses.shproj → Demos/TripExpenses/TripExpenses/TripExpenses/TripExpenses.Shared.shproj

@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <PropertyGroup Label="Globals">
     <ProjectGuid>908b9ab7-c998-4b59-b85e-ec37794fb92b</ProjectGuid>
   </PropertyGroup>
@@ -7,6 +7,6 @@
   <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props" />
   <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props" />
   <PropertyGroup />
-  <Import Project="TripExpenses.projitems" Label="Shared" />
+  <Import Project="TripExpenses.Shared.projitems" Label="Shared" />
   <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets" />
 </Project>

+ 5 - 3
Demos/TripExpenses/TripExpenses/TripExpenses/ViewModels/DetailViewModel.cs

@@ -22,8 +22,10 @@ namespace TripExpenses.ViewModels
     private bool isNew;
 
     INavigation navigation;
+		IDataStore dataStore;
     public DetailViewModel(TripExpense expense, INavigation navigation)
     {
+			dataStore = DependencyService.Get<IDataStore> ();
       this.navigation = navigation;
       if(expense == null)
       {
@@ -66,12 +68,12 @@ namespace TripExpenses.ViewModels
 
 
       if (isNew)
-        await DataStore.Instance.InsertExpenseAsync(expense);
+				await dataStore.InsertExpenseAsync(expense);
       else
-        await DataStore.Instance.UpdateExpenseAsync(expense);
+				await dataStore.UpdateExpenseAsync(expense);
 
 
-      await DataStore.Instance.SyncExpensesAsync();
+			await dataStore.SyncExpensesAsync();
 
       //Send a message to insert/update the expense to all subscribers
       if(isNew)

+ 43 - 3
Demos/TripExpenses/TripExpenses/TripExpenses/ViewModels/ExpensesViewModel.cs

@@ -16,11 +16,12 @@ namespace TripExpenses.ViewModels
     public bool Initialized { get; set; }
 
     public ObservableCollection<TripExpense> Expenses { get; set; }
+		IDataStore dataStore;
 
     public ExpensesViewModel()
-    { 
+		{ 
+			dataStore = DependencyService.Get<IDataStore> ();
       Expenses = new ObservableCollection<TripExpense>();
-
       //Subscibe to insert expenses
       MessagingCenter.Subscribe<TripExpense>(this, "NewExpense", (expense) =>
       {
@@ -55,7 +56,7 @@ namespace TripExpenses.ViewModels
 
       Expenses.Clear();
 
-      var expenses = await DataStore.Instance.GetExpensesAsync();
+			var expenses = await dataStore.GetExpensesAsync();
       foreach (var expense in expenses)
        Expenses.Add(expense);
 
@@ -80,5 +81,44 @@ namespace TripExpenses.ViewModels
       Expenses[index] = expense;
       IsBusy = false;
     }
+
+		private Command<TripExpense> deleteExpense;
+		public ICommand DeleteExpense
+		{
+			get
+			{
+				return deleteExpense ??
+					(deleteExpense = new Command<TripExpense>((expense)=>ExecuteDeleteExpense(expense)));
+			}
+		}
+
+		private async Task ExecuteDeleteExpense(TripExpense expense)
+		{
+			IsBusy = true;
+			await dataStore.DeleteExpenseAsync(expense);
+			await dataStore.SyncExpensesAsync ();
+			Expenses.Remove (expense);
+			IsBusy = false;
+		}
+
+
+		public void SpeakTotal()
+		{
+			var total = 0.0f;
+			var temp = 0.0f;
+			foreach (var expense in Expenses) {
+				
+				if (float.TryParse (expense.Price, out temp))
+					total += temp;
+			}
+
+			var message = "You have a total of " + 
+				Expenses.Count + 
+				" expenses that need to be filed totaling " +
+				total.ToString("C");
+	
+
+
+		}
   }
 }

+ 14 - 5
Demos/TripExpenses/TripExpenses/TripExpenses/Views/DetailsPage.xaml

@@ -1,13 +1,21 @@
 <?xml version="1.0" encoding="utf-8" ?>
 <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
-			 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
 			 x:Class="TripExpenses.Views.DetailsPage"
+		     xmlns:local="clr-namespace:TripExpenses.UI;assembly=TripExpenses.UI"
              Title="Details">
+     <ContentPage.Resources>
+	     <ResourceDictionary>
+	   		<local:MultiTriggerConverter x:Key="dataHasBeenEntered" />
+		</ResourceDictionary>
+	</ContentPage.Resources>
 	<StackLayout Padding="20" Spacing="20">
-        <Entry Placeholder="Expense Name"
+        <Entry x:Name="ExpenseName"
+        	   Placeholder="Expense Name"
                Text="{Binding Name, Mode=TwoWay}"/>
         
-        <Entry Placeholder="0.00"
+        <Entry x:Name="ExpenseTotal"
+               Placeholder="0.00"
                Text="{Binding Price, Mode=TwoWay}"
                Keyboard="Numeric"/>
         
@@ -15,7 +23,6 @@
             <Label Text ="Billable" VerticalOptions="Center"/>
             <Switch IsToggled="{Binding Billable}"/>
         </StackLayout>
-        
         <Picker x:Name="PickerCategory"
                 Title="Category"
                 SelectedIndex="{Binding Category}"/>
@@ -24,7 +31,9 @@
                 BackgroundColor="#77D065"
                 TextColor="#FFFFFF"
                 HorizontalOptions="FillAndExpand"
-                Command="{Binding SaveCommand}"/>
+                Command="{Binding SaveCommand}">
+             
+        </Button>
         
          <ActivityIndicator IsVisible="{Binding IsBusy}"
                             IsRunning="{Binding IsBusy}"/>

+ 3 - 1
Demos/TripExpenses/TripExpenses/TripExpenses/Views/DetailsPage.xaml.cs

@@ -6,11 +6,13 @@ using System.Threading.Tasks;
 using TripExpenses.Models;
 using TripExpenses.ViewModels;
 using Xamarin.Forms;
+using TripExpenses.UI;
 
 namespace TripExpenses.Views
 {
 	public partial class DetailsPage
 	{
+		
 		public DetailViewModel ViewModel
 		{
 			get { return BindingContext as DetailViewModel; }
@@ -20,7 +22,7 @@ namespace TripExpenses.Views
 		public DetailsPage(TripExpense expense)
 		{
 			InitializeComponent();
-
+			Type type = typeof(MultiTriggerConverter);
 			foreach (var item in DetailViewModel.Categories)
 				PickerCategory.Items.Add(item);
 

+ 25 - 21
Demos/TripExpenses/TripExpenses/TripExpenses/Views/ExpenseListPage.xaml

@@ -1,26 +1,30 @@
 <?xml version="1.0" encoding="utf-8" ?>
 <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
-					   xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
-					   x:Class="TripExpenses.Views.ExpenseListPage"
-             Title="Expenses">
+			 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+			 x:Class="TripExpenses.Views.ExpenseListPage"
+			 Title="Expenses"
+       IsBusy="{Binding IsBusy}">
+   <ContentPage.ToolbarItems>
+   	<ToolbarItem x:Name="AddItem" Text="add" Icon="add.png"/>
+   </ContentPage.ToolbarItems>
     <ContentPage.Content>
-        <StackLayout Spacing="10" Padding="10">
-            <ActivityIndicator IsVisible="{Binding IsBusy}"
-                    IsRunning="{Binding IsBusy}"/>
-
-            <ListView x:Name="ExpenseList" ItemsSource="{Binding Expenses}">
-                <ListView.ItemTemplate>
-                    <DataTemplate>
-                        <TextCell Text="{Binding Name}"
-                        Detail="{Binding Price}"/>
-                    </DataTemplate>
-                </ListView.ItemTemplate>
-            </ListView>
-
-            <Button x:Name="ButtonNewExpense"
-                    Text="Add Expense"
-                      BackgroundColor="#77D065"
-                TextColor="#FFFFFF"/>
-        </StackLayout>
+        <ListView x:Name="ExpenseList" 
+        		 ItemsSource="{Binding Expenses}"
+        		 IsPullToRefreshEnabled="true"
+        		 RefreshCommand="{Binding LoadExpenses}"
+        		 IsRefreshing="{Binding IsBusy, Mode=OneWay}">
+            <ListView.ItemTemplate>
+                <DataTemplate>
+                    <TextCell Text="{Binding Name}"
+                    Detail="{Binding Price}">
+                     	<TextCell.ContextActions>
+                     		<MenuItem Clicked="OnDelete"
+           						Text="Delete" IsDestructive="True" 
+           						CommandParameter="{Binding .}"/>
+                     	</TextCell.ContextActions>
+                    </TextCell>
+                </DataTemplate>
+            </ListView.ItemTemplate>
+        </ListView>
     </ContentPage.Content>
 </ContentPage>

+ 12 - 12
Demos/TripExpenses/TripExpenses/TripExpenses/Views/ExpenseListPage.xaml.cs

@@ -19,12 +19,11 @@ namespace TripExpenses.Views
 
 			this.BindingContext = viewModel = new ExpensesViewModel();
 
-			ToolbarItems.Add(new ToolbarItem
-			  {
-				  Name = "refresh",
-				  Icon = "refresh.png",
-				  Command = viewModel.LoadExpenses
-			  });
+			AddItem.Command = new Command (() => {
+				var detailPage = new DetailsPage (null);
+				Navigation.PushAsync (detailPage);
+			});
+
 
 			ExpenseList.ItemTapped += (sender, args) =>
 			{
@@ -36,12 +35,13 @@ namespace TripExpenses.Views
 
 				ExpenseList.SelectedItem = null;
 			};
+				
 
-			ButtonNewExpense.Clicked += async (sender, args) =>
-			{
-				var detailPage = new DetailsPage(null);
-				await Navigation.PushAsync(detailPage);
-			};
+		}
+
+		public void OnDelete (object sender, EventArgs e) {
+			var mi = ((MenuItem)sender);
+			viewModel.DeleteExpense.Execute (mi.CommandParameter);
 		}
 
 
@@ -53,4 +53,4 @@ namespace TripExpenses.Views
 				viewModel.LoadExpenses.Execute(null);
 		}
 	}
-}
+}