mirror of
https://github.com/mgroves/MonodroidStockPortfolio.git
synced 2024-12-25 03:00:21 +00:00
I have screwed up something in git
This commit is contained in:
parent
8de53824b0
commit
e4b07dd8d9
34 changed files with 888 additions and 190 deletions
46
MonoStockPortfolio.Core/AndroidSqliteBase.cs
Normal file
46
MonoStockPortfolio.Core/AndroidSqliteBase.cs
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
using Android.Content;
|
||||||
|
using Android.Database.Sqlite;
|
||||||
|
using Android.Util;
|
||||||
|
|
||||||
|
namespace MonoStockPortfolio.Core
|
||||||
|
{
|
||||||
|
public abstract class AndroidSqliteBase : SQLiteOpenHelper
|
||||||
|
{
|
||||||
|
public const string PORTFOLIO_TABLE_NAME = "Portfolios";
|
||||||
|
public const string POSITION_TABLE_NAME = "Positions";
|
||||||
|
public const string CONFIG_TABLE_NAME = "Config";
|
||||||
|
|
||||||
|
public const string DATABASE_NAME = "stockportfolio.db";
|
||||||
|
public const int DATABASE_VERSION = 1;
|
||||||
|
|
||||||
|
protected AndroidSqliteBase(Context context)
|
||||||
|
: base(context, DATABASE_NAME, null, DATABASE_VERSION)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SQLiteDatabase Db { get { return WritableDatabase; } }
|
||||||
|
|
||||||
|
public override void OnCreate(SQLiteDatabase db)
|
||||||
|
{
|
||||||
|
db.ExecSQL("CREATE TABLE " + PORTFOLIO_TABLE_NAME + " (id INTEGER PRIMARY KEY AUTOINCREMENT, Name TEXT)");
|
||||||
|
db.ExecSQL("CREATE TABLE " + POSITION_TABLE_NAME + " (id INTEGER PRIMARY KEY AUTOINCREMENT, Ticker TEXT, Shares REAL, PricePerShare REAL, ContainingPortfolioID INT)");
|
||||||
|
db.ExecSQL("CREATE TABLE " + CONFIG_TABLE_NAME + " (StockItems TEXT)");
|
||||||
|
|
||||||
|
db.ExecSQL("INSERT INTO " + CONFIG_TABLE_NAME + " (StockItems) VALUES ('2,0,1,3')");
|
||||||
|
db.ExecSQL("INSERT INTO " + PORTFOLIO_TABLE_NAME + " (Name) VALUES ('Sample portfolio')");
|
||||||
|
db.ExecSQL("INSERT INTO " + POSITION_TABLE_NAME + " (Ticker, Shares, PricePerShare, ContainingPortfolioID) VALUES ('GOOG', '500', '593.97', 1)");
|
||||||
|
db.ExecSQL("INSERT INTO " + POSITION_TABLE_NAME + " (Ticker, Shares, PricePerShare, ContainingPortfolioID) VALUES ('AMZN', '500', '180.00', 1)");
|
||||||
|
db.ExecSQL("INSERT INTO " + POSITION_TABLE_NAME + " (Ticker, Shares, PricePerShare, ContainingPortfolioID) VALUES ('AAPL', '500', '322.56', 1)");
|
||||||
|
db.ExecSQL("INSERT INTO " + POSITION_TABLE_NAME + " (Ticker, Shares, PricePerShare, ContainingPortfolioID) VALUES ('MSFT', '500', '27.91', 1)");
|
||||||
|
db.ExecSQL("INSERT INTO " + POSITION_TABLE_NAME + " (Ticker, Shares, PricePerShare, ContainingPortfolioID) VALUES ('NOVL', '500', '5.92', 1)");
|
||||||
|
db.ExecSQL("INSERT INTO " + POSITION_TABLE_NAME + " (Ticker, Shares, PricePerShare, ContainingPortfolioID) VALUES ('S', '500', '4.23', 1)");
|
||||||
|
db.ExecSQL("INSERT INTO " + POSITION_TABLE_NAME + " (Ticker, Shares, PricePerShare, ContainingPortfolioID) VALUES ('VZ', '500', '35.78', 1)");
|
||||||
|
db.ExecSQL("INSERT INTO " + POSITION_TABLE_NAME + " (Ticker, Shares, PricePerShare, ContainingPortfolioID) VALUES ('T', '500', '29.38', 1)");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
|
||||||
|
{
|
||||||
|
Log.Warn("Upgrade", "Nothing to upgrade");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,11 +1,44 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Android.Content;
|
||||||
using MonoStockPortfolio.Entities;
|
using MonoStockPortfolio.Entities;
|
||||||
|
|
||||||
namespace MonoStockPortfolio.Core.Config
|
namespace MonoStockPortfolio.Core.Config
|
||||||
{
|
{
|
||||||
public class AndroidSqliteConfigRepository : IConfigRepository
|
public class AndroidSqliteConfigRepository : AndroidSqliteBase, IConfigRepository
|
||||||
{
|
{
|
||||||
|
public AndroidSqliteConfigRepository(Context context) : base(context)
|
||||||
|
{ }
|
||||||
|
|
||||||
public IEnumerable<StockDataItem> GetStockItems()
|
public IEnumerable<StockDataItem> GetStockItems()
|
||||||
|
{
|
||||||
|
var cursor = Db.Query(CONFIG_TABLE_NAME, new[] { "StockItems" }, null, null, null, null, null);
|
||||||
|
string stockItemsCsv = null;
|
||||||
|
if (cursor.Count > 0)
|
||||||
|
{
|
||||||
|
cursor.MoveToNext();
|
||||||
|
stockItemsCsv = cursor.GetString(0);
|
||||||
|
if (!cursor.IsClosed) cursor.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(stockItemsCsv))
|
||||||
|
{
|
||||||
|
return DefaultItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
return stockItemsCsv.Split(',').Select(i => (StockDataItem)int.Parse(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateStockItems(List<StockDataItem> stockDataItems)
|
||||||
|
{
|
||||||
|
var stockItemsCsv = string.Join(",", stockDataItems.Select(i => ((int) i).ToString()).ToArray());
|
||||||
|
var contentValues = new ContentValues();
|
||||||
|
contentValues.Put("StockItems", stockItemsCsv);
|
||||||
|
Db.Update(CONFIG_TABLE_NAME, contentValues, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// this should never be called, but it's here anyway in case of some catastrophe
|
||||||
|
private static IEnumerable<StockDataItem> DefaultItems()
|
||||||
{
|
{
|
||||||
var items = new List<StockDataItem>();
|
var items = new List<StockDataItem>();
|
||||||
items.Add(StockDataItem.Ticker);
|
items.Add(StockDataItem.Ticker);
|
||||||
|
|
|
@ -6,5 +6,6 @@ namespace MonoStockPortfolio.Core.Config
|
||||||
public interface IConfigRepository
|
public interface IConfigRepository
|
||||||
{
|
{
|
||||||
IEnumerable<StockDataItem> GetStockItems();
|
IEnumerable<StockDataItem> GetStockItems();
|
||||||
|
void UpdateStockItems(List<StockDataItem> stockDataItems);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,25 +0,0 @@
|
||||||
using System;
|
|
||||||
using MonoStockPortfolio.Entities;
|
|
||||||
|
|
||||||
namespace MonoStockPortfolio.Core
|
|
||||||
{
|
|
||||||
public static class EnumExtensions
|
|
||||||
{
|
|
||||||
/// Will get the string value attribute for a given enums value, this will
|
|
||||||
/// only work if you assign the StringValue attribute to
|
|
||||||
/// the items in your enum.
|
|
||||||
public static string GetStringValue(this Enum value)
|
|
||||||
{
|
|
||||||
var type = value.GetType();
|
|
||||||
var fieldInfo = type.GetField(value.ToString());
|
|
||||||
|
|
||||||
var attributes = fieldInfo.GetCustomAttributes(typeof(StringValueAttribute), false) as StringValueAttribute[];
|
|
||||||
|
|
||||||
if (attributes != null)
|
|
||||||
{
|
|
||||||
return attributes.Length > 0 ? attributes[0].StringValue : string.Empty;
|
|
||||||
}
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -31,11 +31,7 @@
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="FileHelpers">
|
|
||||||
<HintPath>..\libs\FileHelpers.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Mono.Android" />
|
<Reference Include="Mono.Android" />
|
||||||
<Reference Include="mscorlib" />
|
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
<Reference Include="System.Xml.Linq" />
|
<Reference Include="System.Xml.Linq" />
|
||||||
|
@ -46,14 +42,15 @@
|
||||||
<Compile Include="Config\IConfigRepository.cs" />
|
<Compile Include="Config\IConfigRepository.cs" />
|
||||||
<Compile Include="DictionaryExtensions.cs" />
|
<Compile Include="DictionaryExtensions.cs" />
|
||||||
<Compile Include="EnumExtensions.cs" />
|
<Compile Include="EnumExtensions.cs" />
|
||||||
|
<Compile Include="AndroidSqliteBase.cs" />
|
||||||
<Compile Include="PortfolioRepositories\AndroidSqlitePortfolioRepository.cs" />
|
<Compile Include="PortfolioRepositories\AndroidSqlitePortfolioRepository.cs" />
|
||||||
<Compile Include="PortfolioRepositories\IPortfolioRepository.cs" />
|
<Compile Include="PortfolioRepositories\IPortfolioRepository.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="Services\IPortfolioService.cs" />
|
<Compile Include="Services\IPortfolioService.cs" />
|
||||||
<Compile Include="Services\PortfolioService.cs" />
|
<Compile Include="Services\PortfolioService.cs" />
|
||||||
|
<Compile Include="StockData\CsvParser.cs" />
|
||||||
|
<Compile Include="StockData\GoogleStockDataProvider.cs" />
|
||||||
<Compile Include="StockData\IStockDataProvider.cs" />
|
<Compile Include="StockData\IStockDataProvider.cs" />
|
||||||
<Compile Include="StockData\YahooFinanceStockData.cs" />
|
|
||||||
<Compile Include="StockData\YahooStockDataProvider.cs" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\MonoStockPortfolio.Entities\MonoStockPortfolio.Entities.csproj">
|
<ProjectReference Include="..\MonoStockPortfolio.Entities\MonoStockPortfolio.Entities.csproj">
|
||||||
|
|
|
@ -7,41 +7,32 @@ using MonoStockPortfolio.Entities;
|
||||||
|
|
||||||
namespace MonoStockPortfolio.Core.PortfolioRepositories
|
namespace MonoStockPortfolio.Core.PortfolioRepositories
|
||||||
{
|
{
|
||||||
public class AndroidSqlitePortfolioRepository : IPortfolioRepository
|
public class AndroidSqlitePortfolioRepository : AndroidSqliteBase, IPortfolioRepository
|
||||||
{
|
{
|
||||||
private OpenHelper _dbHelper;
|
|
||||||
private SQLiteDatabase _db;
|
|
||||||
private const string PORTFOLIO_TABLE_NAME = "Portfolios";
|
|
||||||
private const string DATABASE_NAME = "stockportfolio.db";
|
|
||||||
private const int DATABASE_VERSION = 1;
|
|
||||||
private const string POSITION_TABLE_NAME = "Positions";
|
|
||||||
|
|
||||||
public AndroidSqlitePortfolioRepository(Context context)
|
public AndroidSqlitePortfolioRepository(Context context)
|
||||||
{
|
: base(context)
|
||||||
_dbHelper = new OpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION);
|
{ }
|
||||||
_db = _dbHelper.WritableDatabase;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IList<Portfolio> GetAllPortfolios()
|
public IList<Portfolio> GetAllPortfolios()
|
||||||
{
|
{
|
||||||
var list = new List<Portfolio>();
|
var list = new List<Portfolio>();
|
||||||
var cursor = _db.Query(PORTFOLIO_TABLE_NAME, new[] {"id", "Name"}, null, null, null, null, null);
|
var cursor = Db.Query(PORTFOLIO_TABLE_NAME, new[] { "id", "Name" }, null, null, null, null, null);
|
||||||
if(cursor.Count > 0)
|
if (cursor.Count > 0)
|
||||||
{
|
{
|
||||||
while(cursor.MoveToNext())
|
while (cursor.MoveToNext())
|
||||||
{
|
{
|
||||||
var portfolio = new Portfolio(cursor.GetInt(0));
|
var portfolio = new Portfolio(cursor.GetInt(0));
|
||||||
portfolio.Name = cursor.GetString(1);
|
portfolio.Name = cursor.GetString(1);
|
||||||
list.Add(portfolio);
|
list.Add(portfolio);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!cursor.IsClosed) cursor.Close();
|
if (!cursor.IsClosed) cursor.Close();
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Portfolio GetPortfolioById(long portfolioId)
|
public Portfolio GetPortfolioById(long portfolioId)
|
||||||
{
|
{
|
||||||
var cursor = _db.Query(PORTFOLIO_TABLE_NAME, new[] { "id", "Name" }, " ID = " + portfolioId, null, null, null, null);
|
var cursor = Db.Query(PORTFOLIO_TABLE_NAME, new[] { "id", "Name" }, " ID = " + portfolioId, null, null, null, null);
|
||||||
if (cursor.Count > 0)
|
if (cursor.Count > 0)
|
||||||
{
|
{
|
||||||
cursor.MoveToNext();
|
cursor.MoveToNext();
|
||||||
|
@ -67,26 +58,26 @@ namespace MonoStockPortfolio.Core.PortfolioRepositories
|
||||||
|
|
||||||
public void DeletePortfolioById(int portfolioId)
|
public void DeletePortfolioById(int portfolioId)
|
||||||
{
|
{
|
||||||
_db.BeginTransaction();
|
Db.BeginTransaction();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_db.Delete(PORTFOLIO_TABLE_NAME, "id = " + portfolioId, null);
|
Db.Delete(PORTFOLIO_TABLE_NAME, "id = " + portfolioId, null);
|
||||||
_db.Delete(POSITION_TABLE_NAME, "ContainingPortfolioID = " + portfolioId, null);
|
Db.Delete(POSITION_TABLE_NAME, "ContainingPortfolioID = " + portfolioId, null);
|
||||||
_db.SetTransactionSuccessful();
|
Db.SetTransactionSuccessful();
|
||||||
}
|
}
|
||||||
catch (SQLiteException)
|
catch (SQLiteException)
|
||||||
{
|
{
|
||||||
Log.E("DeletePortfolio", "SQLiteException => Id = " + portfolioId);
|
Log.Error("DeletePortfolio", "SQLiteException => Id = " + portfolioId);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
_db.EndTransaction();
|
Db.EndTransaction();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Portfolio GetPortfolioByName(string portfolioName)
|
public Portfolio GetPortfolioByName(string portfolioName)
|
||||||
{
|
{
|
||||||
var cursor = _db.Query(PORTFOLIO_TABLE_NAME, new[] { "id", "Name" }, " Name = '" + portfolioName + "'", null, null, null, null);
|
var cursor = Db.Query(PORTFOLIO_TABLE_NAME, new[] { "id", "Name" }, " Name = '" + portfolioName + "'", null, null, null, null);
|
||||||
if (cursor.Count > 0)
|
if (cursor.Count > 0)
|
||||||
{
|
{
|
||||||
cursor.MoveToNext();
|
cursor.MoveToNext();
|
||||||
|
@ -100,19 +91,19 @@ namespace MonoStockPortfolio.Core.PortfolioRepositories
|
||||||
|
|
||||||
public void DeletePositionById(long positionId)
|
public void DeletePositionById(long positionId)
|
||||||
{
|
{
|
||||||
_db.Delete(POSITION_TABLE_NAME, "id = " + positionId, null);
|
Db.Delete(POSITION_TABLE_NAME, "id = " + positionId, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Position GetPositionById(long positionId)
|
public Position GetPositionById(long positionId)
|
||||||
{
|
{
|
||||||
Position position = null;
|
Position position = null;
|
||||||
|
|
||||||
var cursor = _db.Query(POSITION_TABLE_NAME, new[] { "id", "Ticker", "Shares", "PricePerShare" }, " id = " + positionId, null, null, null, null);
|
var cursor = Db.Query(POSITION_TABLE_NAME, new[] { "id", "Ticker", "Shares", "PricePerShare" }, " id = " + positionId, null, null, null, null);
|
||||||
if (cursor.Count > 0)
|
if (cursor.Count > 0)
|
||||||
{
|
{
|
||||||
while (cursor.MoveToNext())
|
while (cursor.MoveToNext())
|
||||||
{
|
{
|
||||||
position= new Position(cursor.GetInt(0));
|
position = new Position(cursor.GetInt(0));
|
||||||
position.Ticker = cursor.GetString(1);
|
position.Ticker = cursor.GetString(1);
|
||||||
position.Shares = Convert.ToDecimal(cursor.GetFloat(2));
|
position.Shares = Convert.ToDecimal(cursor.GetFloat(2));
|
||||||
position.PricePerShare = Convert.ToDecimal(cursor.GetFloat(3));
|
position.PricePerShare = Convert.ToDecimal(cursor.GetFloat(3));
|
||||||
|
@ -126,7 +117,7 @@ namespace MonoStockPortfolio.Core.PortfolioRepositories
|
||||||
{
|
{
|
||||||
var list = new List<Position>();
|
var list = new List<Position>();
|
||||||
|
|
||||||
var cursor = _db.Query(POSITION_TABLE_NAME, new[] { "id", "Ticker", "Shares", "PricePerShare" }, " ContainingPortfolioID = " + portfolioId, null, null, null, null);
|
var cursor = Db.Query(POSITION_TABLE_NAME, new[] { "id", "Ticker", "Shares", "PricePerShare" }, " ContainingPortfolioID = " + portfolioId, null, null, null, null);
|
||||||
if (cursor.Count > 0)
|
if (cursor.Count > 0)
|
||||||
{
|
{
|
||||||
while (cursor.MoveToNext())
|
while (cursor.MoveToNext())
|
||||||
|
@ -157,23 +148,23 @@ namespace MonoStockPortfolio.Core.PortfolioRepositories
|
||||||
private void UpdateExistingPortfolio(Portfolio portfolio)
|
private void UpdateExistingPortfolio(Portfolio portfolio)
|
||||||
{
|
{
|
||||||
var portfolioID = portfolio.ID ?? -1;
|
var portfolioID = portfolio.ID ?? -1;
|
||||||
Log.E("UpdateExistingPortfolio", "Portfolios updated: " + _db.Update(PORTFOLIO_TABLE_NAME, GetPortfolioContentValues(portfolio), "id = " + portfolioID, null));
|
Log.Error("UpdateExistingPortfolio", "Portfolios updated: " + Db.Update(PORTFOLIO_TABLE_NAME, GetPortfolioContentValues(portfolio), "id = " + portfolioID, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InsertNewPortfolio(Portfolio portfolio)
|
private void InsertNewPortfolio(Portfolio portfolio)
|
||||||
{
|
{
|
||||||
Log.E("InsertNewPortfolio", "Portfolios inserted: " + _db.Insert(PORTFOLIO_TABLE_NAME, null, GetPortfolioContentValues(portfolio)));
|
Log.Error("InsertNewPortfolio", "Portfolios inserted: " + Db.Insert(PORTFOLIO_TABLE_NAME, null, GetPortfolioContentValues(portfolio)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateExistingPosition(Position position)
|
private void UpdateExistingPosition(Position position)
|
||||||
{
|
{
|
||||||
var positionID = position.ID ?? -1;
|
var positionID = position.ID ?? -1;
|
||||||
Log.E("UpdateExistingPosition", "Positions updated: " + _db.Update(POSITION_TABLE_NAME, GetPositionContentValues(position), "id = " + positionID, null));
|
Log.Error("UpdateExistingPosition", "Positions updated: " + Db.Update(POSITION_TABLE_NAME, GetPositionContentValues(position), "id = " + positionID, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InsertNewPosition(Position position)
|
private void InsertNewPosition(Position position)
|
||||||
{
|
{
|
||||||
Log.E("InsertNewPosition", "Positions inserted: " + _db.Insert(POSITION_TABLE_NAME, null, GetPositionContentValues(position)));
|
Log.Error("InsertNewPosition", "Positions inserted: " + Db.Insert(POSITION_TABLE_NAME, null, GetPositionContentValues(position)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ContentValues GetPortfolioContentValues(Portfolio portfolio)
|
private static ContentValues GetPortfolioContentValues(Portfolio portfolio)
|
||||||
|
@ -192,41 +183,5 @@ namespace MonoStockPortfolio.Core.PortfolioRepositories
|
||||||
positionValues.Put("ContainingPortfolioID", position.ContainingPortfolioID);
|
positionValues.Put("ContainingPortfolioID", position.ContainingPortfolioID);
|
||||||
return positionValues;
|
return positionValues;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private class OpenHelper : SQLiteOpenHelper
|
|
||||||
{
|
|
||||||
public OpenHelper(Context context, string name, SQLiteDatabase.ICursorFactory factory, int version)
|
|
||||||
: base(context, name, factory, version)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnCreate(SQLiteDatabase db)
|
|
||||||
{
|
|
||||||
db.ExecSQL("CREATE TABLE " + PORTFOLIO_TABLE_NAME + " (id INTEGER PRIMARY KEY AUTOINCREMENT, Name TEXT)");
|
|
||||||
db.ExecSQL("CREATE TABLE " + POSITION_TABLE_NAME + " (id INTEGER PRIMARY KEY AUTOINCREMENT, Ticker TEXT, Shares REAL, PricePerShare REAL, ContainingPortfolioID INT)");
|
|
||||||
|
|
||||||
db.ExecSQL("INSERT INTO " + PORTFOLIO_TABLE_NAME + " (Name) VALUES ('Sample portfolio')");
|
|
||||||
db.ExecSQL("INSERT INTO " + POSITION_TABLE_NAME + " (Ticker, Shares, PricePerShare, ContainingPortfolioID) VALUES ('GOOG', '500', '593.97', 1)");
|
|
||||||
db.ExecSQL("INSERT INTO " + POSITION_TABLE_NAME + " (Ticker, Shares, PricePerShare, ContainingPortfolioID) VALUES ('AMZN', '500', '180.00', 1)");
|
|
||||||
db.ExecSQL("INSERT INTO " + POSITION_TABLE_NAME + " (Ticker, Shares, PricePerShare, ContainingPortfolioID) VALUES ('AAPL', '500', '322.56', 1)");
|
|
||||||
db.ExecSQL("INSERT INTO " + POSITION_TABLE_NAME + " (Ticker, Shares, PricePerShare, ContainingPortfolioID) VALUES ('MSFT', '500', '27.91', 1)");
|
|
||||||
db.ExecSQL("INSERT INTO " + POSITION_TABLE_NAME + " (Ticker, Shares, PricePerShare, ContainingPortfolioID) VALUES ('NOVL', '500', '5.92', 1)");
|
|
||||||
db.ExecSQL("INSERT INTO " + POSITION_TABLE_NAME + " (Ticker, Shares, PricePerShare, ContainingPortfolioID) VALUES ('S', '500', '4.23', 1)");
|
|
||||||
db.ExecSQL("INSERT INTO " + POSITION_TABLE_NAME + " (Ticker, Shares, PricePerShare, ContainingPortfolioID) VALUES ('VZ', '500', '35.78', 1)");
|
|
||||||
db.ExecSQL("INSERT INTO " + POSITION_TABLE_NAME + " (Ticker, Shares, PricePerShare, ContainingPortfolioID) VALUES ('T', '500', '29.38', 1)");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
|
|
||||||
{
|
|
||||||
Log.W("Upgrade", "Nothing to upgrade");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -50,7 +50,7 @@ namespace MonoStockPortfolio.Core.Services
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Log.E("GetDetailedItems", ex.ToString());
|
Log.Error("GetDetailedItems", ex.ToString());
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
38
MonoStockPortfolio.Core/StockData/CsvParser.cs
Normal file
38
MonoStockPortfolio.Core/StockData/CsvParser.cs
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using Android.Util;
|
||||||
|
|
||||||
|
namespace MonoStockPortfolio.Core.StockData
|
||||||
|
{
|
||||||
|
public class CsvParser
|
||||||
|
{
|
||||||
|
public static IEnumerable<string[]> ParseCsvIntoStockQuotes(string csvText)
|
||||||
|
{
|
||||||
|
using (var sr = new StringReader(csvText))
|
||||||
|
{
|
||||||
|
var lines = new List<string[]>();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string line;
|
||||||
|
while ((line = sr.ReadLine()) != null)
|
||||||
|
{
|
||||||
|
var tokens = line.Split(',');
|
||||||
|
for (int i = 0; i < tokens.Length; i++)
|
||||||
|
{
|
||||||
|
tokens[i] = tokens[i].Trim('\"');
|
||||||
|
}
|
||||||
|
lines.Add(tokens);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
Log.Error("ParseCSV", "Error in retrieving/parsing stock information");
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
106
MonoStockPortfolio.Core/StockData/GoogleStockDataProvider.cs
Normal file
106
MonoStockPortfolio.Core/StockData/GoogleStockDataProvider.cs
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using MonoStockPortfolio.Entities;
|
||||||
|
|
||||||
|
namespace MonoStockPortfolio.Core.StockData
|
||||||
|
{
|
||||||
|
public class GoogleStockDataProvider : IStockDataProvider
|
||||||
|
{
|
||||||
|
private const string BASE_URL = "http://www.google.com/finance/info?infotype=infoquoteall&q=";
|
||||||
|
/*
|
||||||
|
http://code.google.com/p/qsb-mac-plugins/source/browse/trunk/stock-quoter/trunk/StockQuoter.py?r=4
|
||||||
|
The Google Finance feed can return some or all of the following keys:
|
||||||
|
|
||||||
|
avvo * Average volume (float with multiplier, like '3.54M')
|
||||||
|
beta * Beta (float)
|
||||||
|
c * Amount of change while open (float)
|
||||||
|
ccol * (unknown) (chars)
|
||||||
|
cl Last perc. change
|
||||||
|
cp * Change perc. while open (float)
|
||||||
|
e * Exchange (text, like 'NASDAQ')
|
||||||
|
ec * After hours last change from close (float)
|
||||||
|
eccol * (unknown) (chars)
|
||||||
|
ecp * After hours last chage perc. from close (float)
|
||||||
|
el * After. hours last quote (float)
|
||||||
|
el_cur * (unknown) (float)
|
||||||
|
elt After hours last quote time (unknown)
|
||||||
|
eo * Exchange Open (0 or 1)
|
||||||
|
eps * Earnings per share (float)
|
||||||
|
fwpe Forward PE ratio (float)
|
||||||
|
hi * Price high (float)
|
||||||
|
hi52 * 52 weeks high (float)
|
||||||
|
id * Company id (identifying number)
|
||||||
|
l * Last value while open (float)
|
||||||
|
l_cur * Last value at close (like 'l')
|
||||||
|
lo * Price low (float)
|
||||||
|
lo52 * 52 weeks low (float)
|
||||||
|
lt Last value date/time
|
||||||
|
ltt Last trade time (Same as "lt" without the data)
|
||||||
|
mc * Market cap. (float with multiplier, like '123.45B')
|
||||||
|
name * Company name (text)
|
||||||
|
op * Open price (float)
|
||||||
|
pe * PE ratio (float)
|
||||||
|
t * Ticker (text)
|
||||||
|
type * Type (i.e. 'Company')
|
||||||
|
vo * Volume (float with multiplier, like '3.54M')
|
||||||
|
*/
|
||||||
|
|
||||||
|
public IEnumerable<StockQuote> GetStockQuotes(IEnumerable<string> tickers)
|
||||||
|
{
|
||||||
|
var tickerCsv = string.Join(",", tickers.ToArray());
|
||||||
|
var url = BASE_URL + tickerCsv;
|
||||||
|
var jsonResults = ScrapeUrl(url).Split('}');
|
||||||
|
|
||||||
|
return jsonResults.Select(MapJsonToStockitems);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected StockQuote MapJsonToStockitems(string jsonResults)
|
||||||
|
{
|
||||||
|
using(var sr = new StringReader(jsonResults))
|
||||||
|
{
|
||||||
|
var sq = new StockQuote();
|
||||||
|
string line;
|
||||||
|
while((line = sr.ReadLine()) != null)
|
||||||
|
{
|
||||||
|
if(line.StartsWith(",\"t\""))
|
||||||
|
{
|
||||||
|
sq.Ticker = line.Replace(",\"t\" : ", "").Trim().Trim('"');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(line.StartsWith(",\"c\""))
|
||||||
|
{
|
||||||
|
sq.Change = decimal.Parse(line.Replace(",\"c\" : ", "").Trim().Trim('"'));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(line.StartsWith(",\"l\""))
|
||||||
|
{
|
||||||
|
sq.LastTradePrice = decimal.Parse(line.Replace(",\"l\" : ", "").Trim().Trim('"'));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(line.StartsWith(",\"ltt\""))
|
||||||
|
{
|
||||||
|
sq.LastTradeTime = line.Replace(",\"ltt\":", "").Trim().Trim('"').Replace("EST","").Trim();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sq;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ScrapeUrl(string url)
|
||||||
|
{
|
||||||
|
string resultCsv;
|
||||||
|
var req = WebRequest.Create(url);
|
||||||
|
var resp = req.GetResponse();
|
||||||
|
using (var sr = new StreamReader(resp.GetResponseStream()))
|
||||||
|
{
|
||||||
|
resultCsv = sr.ReadToEnd();
|
||||||
|
sr.Close();
|
||||||
|
}
|
||||||
|
return resultCsv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -31,7 +31,6 @@
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="mscorlib" />
|
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
<Reference Include="System.Xml.Linq" />
|
<Reference Include="System.Xml.Linq" />
|
||||||
|
|
|
@ -3,22 +3,22 @@ namespace MonoStockPortfolio.Entities
|
||||||
public enum StockDataItem
|
public enum StockDataItem
|
||||||
{
|
{
|
||||||
[StringValue("Change")]
|
[StringValue("Change")]
|
||||||
Change,
|
Change = 0,
|
||||||
[StringValue("Gain/Loss")]
|
[StringValue("Gain/Loss")]
|
||||||
GainLoss,
|
GainLoss = 1,
|
||||||
[StringValue("Ticker")]
|
[StringValue("Ticker")]
|
||||||
Ticker,
|
Ticker = 2,
|
||||||
[StringValue("Time")]
|
[StringValue("Time")]
|
||||||
Time,
|
Time = 3,
|
||||||
[StringValue("Volume")]
|
[StringValue("Volume")]
|
||||||
Volume,
|
Volume = 4,
|
||||||
[StringValue("Price")]
|
[StringValue("Price")]
|
||||||
LastTradePrice,
|
LastTradePrice = 5,
|
||||||
[StringValue("Price-RT")]
|
[StringValue("Price-RT")]
|
||||||
RealTimeLastTradeWithTime,
|
RealTimeLastTradeWithTime = 6,
|
||||||
[StringValue("Change-RT")]
|
[StringValue("Change-RT")]
|
||||||
ChangeRealTime,
|
ChangeRealTime = 7,
|
||||||
[StringValue("Gain/Loss-RT")]
|
[StringValue("Gain/Loss-RT")]
|
||||||
GainLossRealTime
|
GainLossRealTime = 8
|
||||||
}
|
}
|
||||||
}
|
}
|
47
MonoStockPortfolio.Tests/CsvParserTests.cs
Normal file
47
MonoStockPortfolio.Tests/CsvParserTests.cs
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
using System.Linq;
|
||||||
|
using MonoStockPortfolio.Core.StockData;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace MonoStockPortfolio.Tests
|
||||||
|
{
|
||||||
|
public class CsvParserTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Can_parse_a_single_line_with_a_single_token()
|
||||||
|
{
|
||||||
|
var line = "XIN";
|
||||||
|
var result = CsvParser.ParseCsvIntoStockQuotes(line);
|
||||||
|
|
||||||
|
Assert.Equal(result.Count(), 1);
|
||||||
|
Assert.Equal(result.First()[0], "XIN");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Can_parse_two_lines_with_a_single_token_each()
|
||||||
|
{
|
||||||
|
var line = "XIN\nMSFT";
|
||||||
|
var result = CsvParser.ParseCsvIntoStockQuotes(line);
|
||||||
|
|
||||||
|
Assert.Equal(result.Count(), 2);
|
||||||
|
Assert.Equal(result.First()[0], "XIN");
|
||||||
|
Assert.Equal(result.ElementAt(1)[0], "MSFT");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Can_parse_a_more_complex_set()
|
||||||
|
{
|
||||||
|
var line = @"""XIN"",2.41,""Xinyuan Real Esta"",269244,-0.03,""4:00pm"",""N/A - <b>2.41</b>"",""-0.03""";
|
||||||
|
var result = CsvParser.ParseCsvIntoStockQuotes(line);
|
||||||
|
|
||||||
|
Assert.Equal(result.Count(), 1);
|
||||||
|
Assert.Equal(result.First()[0], "XIN");
|
||||||
|
Assert.Equal(result.First()[1], "2.41");
|
||||||
|
Assert.Equal(result.First()[2], "Xinyuan Real Esta");
|
||||||
|
Assert.Equal(result.First()[3], "269244");
|
||||||
|
Assert.Equal(result.First()[4], "-0.03");
|
||||||
|
Assert.Equal(result.First()[5], "4:00pm");
|
||||||
|
Assert.Equal(result.First()[6], "N/A - <b>2.41</b>");
|
||||||
|
Assert.Equal(result.First()[7], "-0.03");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
170
MonoStockPortfolio.Tests/GoogleStockQuoteTests.cs
Normal file
170
MonoStockPortfolio.Tests/GoogleStockQuoteTests.cs
Normal file
|
@ -0,0 +1,170 @@
|
||||||
|
using MonoStockPortfolio.Core.StockData;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace MonoStockPortfolio.Tests
|
||||||
|
{
|
||||||
|
public class GoogleStockQuoteTests : GoogleStockDataProvider
|
||||||
|
{
|
||||||
|
#region ExampleJson : Example Json Result
|
||||||
|
private string ExampleJson =
|
||||||
|
@"
|
||||||
|
// [ {
|
||||||
|
""id"": ""720780""
|
||||||
|
,""t"" : ""XIN""
|
||||||
|
,""e"" : ""NYSE""
|
||||||
|
,""l"" : ""2.41""
|
||||||
|
,""l_cur"" : ""2.41""
|
||||||
|
,""s"": ""0""
|
||||||
|
,""ltt"":""4:00PM EST""
|
||||||
|
,""lt"" : ""Feb 4, 4:00PM EST""
|
||||||
|
,""c"" : ""-0.03""
|
||||||
|
,""cp"" : ""-1.23""
|
||||||
|
,""ccol"" : ""chr""
|
||||||
|
,""eo"" : """"
|
||||||
|
,""delay"": """"
|
||||||
|
,""op"" : ""2.45""
|
||||||
|
,""hi"" : ""2.45""
|
||||||
|
,""lo"" : ""2.39""
|
||||||
|
,""vo"" : ""269,244.00""
|
||||||
|
,""avvo"" : ""352,270.00""
|
||||||
|
,""hi52"" : ""4.30""
|
||||||
|
,""lo52"" : ""2.20""
|
||||||
|
,""mc"" : ""182.78M""
|
||||||
|
,""pe"" : ""3.47""
|
||||||
|
,""fwpe"" : """"
|
||||||
|
,""beta"" : ""1.30""
|
||||||
|
,""eps"" : ""0.69""
|
||||||
|
,""name"" : ""Xinyuan Real Estate Co., Ltd. (ADR)""
|
||||||
|
,""type"" : ""Company""
|
||||||
|
}
|
||||||
|
,{
|
||||||
|
""id"": ""358464""
|
||||||
|
,""t"" : ""MSFT""
|
||||||
|
,""e"" : ""NASDAQ""
|
||||||
|
,""l"" : ""27.77""
|
||||||
|
,""l_cur"" : ""27.77""
|
||||||
|
,""s"": ""2""
|
||||||
|
,""ltt"":""4:01PM EST""
|
||||||
|
,""lt"" : ""Feb 4, 4:01PM EST""
|
||||||
|
,""c"" : ""+0.12""
|
||||||
|
,""cp"" : ""0.43""
|
||||||
|
,""ccol"" : ""chg""
|
||||||
|
,""el"": ""27.72""
|
||||||
|
,""el_cur"": ""27.72""
|
||||||
|
,""elt"" : ""Feb 4, 7:39PM EST""
|
||||||
|
,""ec"" : ""-0.05""
|
||||||
|
,""ecp"" : ""-0.18""
|
||||||
|
,""eccol"" : ""chr""
|
||||||
|
,""div"" : ""0.16""
|
||||||
|
,""yld"" : ""2.30""
|
||||||
|
,""eo"" : """"
|
||||||
|
,""delay"": """"
|
||||||
|
,""op"" : ""27.73""
|
||||||
|
,""hi"" : ""27.84""
|
||||||
|
,""lo"" : ""27.51""
|
||||||
|
,""vo"" : ""40.42M""
|
||||||
|
,""avvo"" : ""55.50M""
|
||||||
|
,""hi52"" : ""31.58""
|
||||||
|
,""lo52"" : ""22.73""
|
||||||
|
,""mc"" : ""233.33B""
|
||||||
|
,""pe"" : ""11.77""
|
||||||
|
,""fwpe"" : """"
|
||||||
|
,""beta"" : ""1.06""
|
||||||
|
,""eps"" : ""2.36""
|
||||||
|
,""name"" : ""Microsoft Corporation""
|
||||||
|
,""type"" : ""Company""
|
||||||
|
}
|
||||||
|
,{
|
||||||
|
""id"": ""22144""
|
||||||
|
,""t"" : ""AAPL""
|
||||||
|
,""e"" : ""NASDAQ""
|
||||||
|
,""l"" : ""346.50""
|
||||||
|
,""l_cur"" : ""346.50""
|
||||||
|
,""s"": ""2""
|
||||||
|
,""ltt"":""4:02PM EST""
|
||||||
|
,""lt"" : ""Feb 4, 4:02PM EST""
|
||||||
|
,""c"" : ""+3.06""
|
||||||
|
,""cp"" : ""0.89""
|
||||||
|
,""ccol"" : ""chg""
|
||||||
|
,""el"": ""346.48""
|
||||||
|
,""el_cur"": ""346.48""
|
||||||
|
,""elt"" : ""Feb 4, 7:59PM EST""
|
||||||
|
,""ec"" : ""-0.02""
|
||||||
|
,""ecp"" : ""-0.01""
|
||||||
|
,""eccol"" : ""chr""
|
||||||
|
,""div"" : """"
|
||||||
|
,""yld"" : """"
|
||||||
|
,""eo"" : """"
|
||||||
|
,""delay"": """"
|
||||||
|
,""op"" : ""343.76""
|
||||||
|
,""hi"" : ""346.70""
|
||||||
|
,""lo"" : ""343.51""
|
||||||
|
,""vo"" : ""11.49M""
|
||||||
|
,""avvo"" : ""15.58M""
|
||||||
|
,""hi52"" : ""348.60""
|
||||||
|
,""lo52"" : ""190.85""
|
||||||
|
,""mc"" : ""319.22B""
|
||||||
|
,""pe"" : ""19.35""
|
||||||
|
,""fwpe"" : """"
|
||||||
|
,""beta"" : ""1.38""
|
||||||
|
,""eps"" : ""17.91""
|
||||||
|
,""name"" : ""Apple Inc.""
|
||||||
|
,""type"" : ""Company""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
";
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private string[] SplitResults
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return ExampleJson.Split('}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Test_ticker()
|
||||||
|
{
|
||||||
|
var results = base.MapJsonToStockitems(SplitResults[0]);
|
||||||
|
Assert.Equal(results.Ticker,"XIN");
|
||||||
|
results = base.MapJsonToStockitems(SplitResults[1]);
|
||||||
|
Assert.Equal(results.Ticker,"MSFT");
|
||||||
|
results = base.MapJsonToStockitems(SplitResults[2]);
|
||||||
|
Assert.Equal(results.Ticker,"AAPL");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Test_change()
|
||||||
|
{
|
||||||
|
var results = base.MapJsonToStockitems(SplitResults[0]);
|
||||||
|
Assert.Equal(results.Change, -0.03M);
|
||||||
|
results = base.MapJsonToStockitems(SplitResults[1]);
|
||||||
|
Assert.Equal(results.Change, 0.12M);
|
||||||
|
results = base.MapJsonToStockitems(SplitResults[2]);
|
||||||
|
Assert.Equal(results.Change, 3.06M);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Test_last_price()
|
||||||
|
{
|
||||||
|
var results = base.MapJsonToStockitems(SplitResults[0]);
|
||||||
|
Assert.Equal(results.LastTradePrice, 2.41M);
|
||||||
|
results = base.MapJsonToStockitems(SplitResults[1]);
|
||||||
|
Assert.Equal(results.LastTradePrice, 27.77M);
|
||||||
|
results = base.MapJsonToStockitems(SplitResults[2]);
|
||||||
|
Assert.Equal(results.LastTradePrice, 346.50M);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Test_time()
|
||||||
|
{
|
||||||
|
var results = base.MapJsonToStockitems(SplitResults[0]);
|
||||||
|
Assert.Equal(results.LastTradeTime, "4:00PM");
|
||||||
|
results = base.MapJsonToStockitems(SplitResults[1]);
|
||||||
|
Assert.Equal(results.LastTradeTime, "4:01PM");
|
||||||
|
results = base.MapJsonToStockitems(SplitResults[2]);
|
||||||
|
Assert.Equal(results.LastTradeTime, "4:02PM");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
86
MonoStockPortfolio.Tests/MonoStockPortfolio.Tests.csproj
Normal file
86
MonoStockPortfolio.Tests/MonoStockPortfolio.Tests.csproj
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProductVersion>8.0.30703</ProductVersion>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
<ProjectGuid>{C2797FAB-AFAB-49F6-9131-FC9BF03CAB9D}</ProjectGuid>
|
||||||
|
<ProjectTypeGuids>{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||||
|
<OutputType>Library</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>MonoStockPortfolio.Tests</RootNamespace>
|
||||||
|
<AssemblyName>MonoStockPortfolio.Tests</AssemblyName>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Mono.Android">
|
||||||
|
<Private>True</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="mscorlib">
|
||||||
|
<Private>True</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System">
|
||||||
|
<Private>True</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Core">
|
||||||
|
<Private>True</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Xml.Linq">
|
||||||
|
<Private>True</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Xml">
|
||||||
|
<Private>True</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="xunit">
|
||||||
|
<HintPath>..\libs\xunit.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="CsvParserTests.cs" />
|
||||||
|
<Compile Include="GoogleStockQuoteTests.cs" />
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\MonoStockPortfolio.Core\MonoStockPortfolio.Core.csproj">
|
||||||
|
<Project>{251E7BB4-CFE2-4DE4-9E2A-AAE1AF41C8CB}</Project>
|
||||||
|
<Name>MonoStockPortfolio.Core</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\MonoStockPortfolio.Entities\MonoStockPortfolio.Entities.csproj">
|
||||||
|
<Project>{05A57650-3B41-46FF-9EAD-9112B5EFBEED}</Project>
|
||||||
|
<Name>MonoStockPortfolio.Entities</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\MonoStockPortfolio\MonoStockPortfolio.csproj">
|
||||||
|
<Project>{E23D8575-CE4E-4716-B9C7-70115D23ADBB}</Project>
|
||||||
|
<Name>MonoStockPortfolio</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="PostSharp.Custom.targets" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildExtensionsPath)\Novell\Novell.MonoDroid.CSharp.targets" />
|
||||||
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
<Target Name="BeforeBuild">
|
||||||
|
</Target>
|
||||||
|
<Target Name="AfterBuild">
|
||||||
|
</Target>
|
||||||
|
-->
|
||||||
|
</Project>
|
6
MonoStockPortfolio.Tests/PostSharp.Custom.targets
Normal file
6
MonoStockPortfolio.Tests/PostSharp.Custom.targets
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<PostSharpAssemblyBindingPolicySet>Silverlight20</PostSharpAssemblyBindingPolicySet>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
29
MonoStockPortfolio.Tests/Properties/AssemblyInfo.cs
Normal file
29
MonoStockPortfolio.Tests/Properties/AssemblyInfo.cs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyTitle("MonoStockPortfolio.Tests")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("Microsoft")]
|
||||||
|
[assembly: AssemblyProduct("MonoStockPortfolio.Tests")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
|
// by using the '*' as shown below:
|
||||||
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
|
[assembly: AssemblyVersion("1.0.0.0")]
|
||||||
|
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
@ -8,15 +8,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "libs", "libs", "{643BA3D4-E
|
||||||
libs\FileHelpers.dll = libs\FileHelpers.dll
|
libs\FileHelpers.dll = libs\FileHelpers.dll
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "assets", "assets", "{4EE7F6AD-B8A9-4402-800E-E4C8AE0FF8FB}"
|
|
||||||
ProjectSection(SolutionItems) = preProject
|
|
||||||
assets\UInotes.txt = assets\UInotes.txt
|
|
||||||
EndProjectSection
|
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoStockPortfolio.Core", "MonoStockPortfolio.Core\MonoStockPortfolio.Core.csproj", "{251E7BB4-CFE2-4DE4-9E2A-AAE1AF41C8CB}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoStockPortfolio.Core", "MonoStockPortfolio.Core\MonoStockPortfolio.Core.csproj", "{251E7BB4-CFE2-4DE4-9E2A-AAE1AF41C8CB}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoStockPortfolio.Entities", "MonoStockPortfolio.Entities\MonoStockPortfolio.Entities.csproj", "{05A57650-3B41-46FF-9EAD-9112B5EFBEED}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoStockPortfolio.Entities", "MonoStockPortfolio.Entities\MonoStockPortfolio.Entities.csproj", "{05A57650-3B41-46FF-9EAD-9112B5EFBEED}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoStockPortfolio.Tests", "MonoStockPortfolio.Tests\MonoStockPortfolio.Tests.csproj", "{C2797FAB-AFAB-49F6-9131-FC9BF03CAB9D}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
@ -35,6 +32,10 @@ Global
|
||||||
{05A57650-3B41-46FF-9EAD-9112B5EFBEED}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{05A57650-3B41-46FF-9EAD-9112B5EFBEED}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{05A57650-3B41-46FF-9EAD-9112B5EFBEED}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{05A57650-3B41-46FF-9EAD-9112B5EFBEED}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{05A57650-3B41-46FF-9EAD-9112B5EFBEED}.Release|Any CPU.Build.0 = Release|Any CPU
|
{05A57650-3B41-46FF-9EAD-9112B5EFBEED}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{C2797FAB-AFAB-49F6-9131-FC9BF03CAB9D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{C2797FAB-AFAB-49F6-9131-FC9BF03CAB9D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{C2797FAB-AFAB-49F6-9131-FC9BF03CAB9D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{C2797FAB-AFAB-49F6-9131-FC9BF03CAB9D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
70
MonoStockPortfolio/Activites/ConfigActivity.cs
Normal file
70
MonoStockPortfolio/Activites/ConfigActivity.cs
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Android.App;
|
||||||
|
using Android.Content;
|
||||||
|
using Android.OS;
|
||||||
|
using Android.Preferences;
|
||||||
|
using MonoStockPortfolio.Core.Config;
|
||||||
|
using MonoStockPortfolio.Entities;
|
||||||
|
using MonoStockPortfolio.Framework;
|
||||||
|
using MonoStockPortfolio.Core;
|
||||||
|
|
||||||
|
namespace MonoStockPortfolio.Activites
|
||||||
|
{
|
||||||
|
[Activity(Label = "Config")]
|
||||||
|
public class ConfigActivity : PreferenceActivity
|
||||||
|
{
|
||||||
|
[IoC] private IConfigRepository _repo;
|
||||||
|
private StockItemPreference[] _stockItemsConfig;
|
||||||
|
|
||||||
|
protected override void OnCreate(Bundle bundle)
|
||||||
|
{
|
||||||
|
base.OnCreate(bundle);
|
||||||
|
|
||||||
|
AddPreferencesFromResource(Resource.Layout.config);
|
||||||
|
|
||||||
|
_stockItemsConfig = StockItemPreference.BuildList(_repo.GetStockItems()).ToArray();
|
||||||
|
|
||||||
|
var customPref = FindPreference("customStockItems");
|
||||||
|
customPref.PreferenceClick += customPref_PreferenceClick;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool customPref_PreferenceClick(Preference preference)
|
||||||
|
{
|
||||||
|
IEnumerable<char>[] stockItemsDisplay = _stockItemsConfig.OrderBy(i => i.StockDataItem).Select(i => i.StockDataItem.GetStringValue()).ToArray();
|
||||||
|
bool[] allitemschecked = _stockItemsConfig.OrderBy(i => i.StockDataItem).Select(i => i.IsChecked).ToArray();
|
||||||
|
|
||||||
|
var dialog = new AlertDialog.Builder(this);
|
||||||
|
dialog.SetMultiChoiceItems(stockItemsDisplay, allitemschecked, clickCallback);
|
||||||
|
dialog.SetTitle("Select columns");
|
||||||
|
dialog.SetPositiveButton("Save", okCallback);
|
||||||
|
dialog.Create().Show();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void okCallback(object sender, DialogClickEventArgs e)
|
||||||
|
{
|
||||||
|
var list = _stockItemsConfig.Where(i => i.IsChecked).Select(i => i.StockDataItem).ToList();
|
||||||
|
_repo.UpdateStockItems(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clickCallback(object sender, DialogMultiChoiceClickEventArgs e)
|
||||||
|
{
|
||||||
|
_stockItemsConfig[e.Which].IsChecked = e.IsChecked;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ClassName { get { return "monostockportfolio.activites.ConfigActivity"; } }
|
||||||
|
|
||||||
|
private class StockItemPreference
|
||||||
|
{
|
||||||
|
public static IEnumerable<StockItemPreference> BuildList(IEnumerable<StockDataItem> checkedItems)
|
||||||
|
{
|
||||||
|
var allitems = StockDataItem.Change.GetValues<StockDataItem>();
|
||||||
|
|
||||||
|
return allitems.Select(item => new StockItemPreference {StockDataItem = item, IsChecked = checkedItems.Contains(item)});
|
||||||
|
}
|
||||||
|
public StockDataItem StockDataItem { get; private set; }
|
||||||
|
public bool IsChecked { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,7 +16,7 @@ namespace MonoStockPortfolio.Activites
|
||||||
{
|
{
|
||||||
base.OnCreate(bundle);
|
base.OnCreate(bundle);
|
||||||
|
|
||||||
SetContentView(Resource.layout.addportfolio);
|
SetContentView(Resource.Layout.addportfolio);
|
||||||
|
|
||||||
WireUpEvents();
|
WireUpEvents();
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ namespace MonoStockPortfolio.Activites
|
||||||
public static string Extra_PortfolioID { get { return "monoStockPortfolio.EditPortfolioActivity.PortfolioID"; } }
|
public static string Extra_PortfolioID { get { return "monoStockPortfolio.EditPortfolioActivity.PortfolioID"; } }
|
||||||
public long ThisPortfolioId { get { return Intent.GetLongExtra(Extra_PortfolioID, -1); } }
|
public long ThisPortfolioId { get { return Intent.GetLongExtra(Extra_PortfolioID, -1); } }
|
||||||
|
|
||||||
protected Button SaveButton { get { return FindViewById<Button>(Resource.id.btnSave); } }
|
protected Button SaveButton { get { return FindViewById<Button>(Resource.Id.btnSave); } }
|
||||||
protected EditText PortfolioName { get { return FindViewById<EditText>(Resource.id.portfolioName); } }
|
protected EditText PortfolioName { get { return FindViewById<EditText>(Resource.Id.portfolioName); } }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -16,7 +16,7 @@ namespace MonoStockPortfolio.Activites
|
||||||
{
|
{
|
||||||
base.OnCreate(bundle);
|
base.OnCreate(bundle);
|
||||||
|
|
||||||
SetContentView(Resource.layout.addposition);
|
SetContentView(Resource.Layout.addposition);
|
||||||
|
|
||||||
var positionId = ThisPositionId;
|
var positionId = ThisPositionId;
|
||||||
if (positionId != -1)
|
if (positionId != -1)
|
||||||
|
|
|
@ -10,9 +10,9 @@ namespace MonoStockPortfolio.Activites
|
||||||
public static string Extra_PositionID { get { return "monoStockPortfolio.EditPositionActivity.PositionID"; } }
|
public static string Extra_PositionID { get { return "monoStockPortfolio.EditPositionActivity.PositionID"; } }
|
||||||
public long ThisPositionId { get { return Intent.GetLongExtra(Extra_PositionID, -1); } }
|
public long ThisPositionId { get { return Intent.GetLongExtra(Extra_PositionID, -1); } }
|
||||||
|
|
||||||
protected EditText TickerTextBox { get { return FindViewById<EditText>(Resource.id.addPositionTicker); } }
|
protected EditText TickerTextBox { get { return FindViewById<EditText>(Resource.Id.addPositionTicker); } }
|
||||||
protected EditText PriceTextBox { get { return FindViewById<EditText>(Resource.id.addPositionPrice); } }
|
protected EditText PriceTextBox { get { return FindViewById<EditText>(Resource.Id.addPositionPrice); } }
|
||||||
protected EditText SharesTextBox { get { return FindViewById<EditText>(Resource.id.addPositionShares); } }
|
protected EditText SharesTextBox { get { return FindViewById<EditText>(Resource.Id.addPositionShares); } }
|
||||||
protected Button SaveButton { get { return FindViewById<Button>(Resource.id.addPositionSaveButton); } }
|
protected Button SaveButton { get { return FindViewById<Button>(Resource.Id.addPositionSaveButton); } }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,6 +4,7 @@ using System.Linq;
|
||||||
using Android.App;
|
using Android.App;
|
||||||
using Android.Content;
|
using Android.Content;
|
||||||
using Android.OS;
|
using Android.OS;
|
||||||
|
using Android.Views;
|
||||||
using Android.Widget;
|
using Android.Widget;
|
||||||
using MonoStockPortfolio.Core.PortfolioRepositories;
|
using MonoStockPortfolio.Core.PortfolioRepositories;
|
||||||
using MonoStockPortfolio.Entities;
|
using MonoStockPortfolio.Entities;
|
||||||
|
@ -22,7 +23,7 @@ namespace MonoStockPortfolio.Activites
|
||||||
{
|
{
|
||||||
base.OnCreate(bundle);
|
base.OnCreate(bundle);
|
||||||
|
|
||||||
SetContentView(Resource.layout.main);
|
SetContentView(Resource.Layout.main);
|
||||||
|
|
||||||
RefreshList();
|
RefreshList();
|
||||||
|
|
||||||
|
@ -33,7 +34,7 @@ namespace MonoStockPortfolio.Activites
|
||||||
{
|
{
|
||||||
_portfolios = _repo.GetAllPortfolios();
|
_portfolios = _repo.GetAllPortfolios();
|
||||||
|
|
||||||
var listAdapter = new ArrayAdapter<string>(this, Android.R.Layout.SimpleListItem1, _portfolios.Select(p => p.Name).ToList());
|
var listAdapter = new ArrayAdapter<string>(this, Android.Resource.Layout.SimpleListItem1, _portfolios.Select(p => p.Name).ToList());
|
||||||
PortfolioListView.Adapter = listAdapter;
|
PortfolioListView.Adapter = listAdapter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,6 +80,32 @@ namespace MonoStockPortfolio.Activites
|
||||||
return base.OnContextItemSelected(item);
|
return base.OnContextItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool OnCreateOptionsMenu(IMenu menu)
|
||||||
|
{
|
||||||
|
var configItem = menu.Add(0, 1, 1, "Config");
|
||||||
|
configItem.SetIcon(Android.Resource.Drawable.IcMenuPreferences);
|
||||||
|
var exitItem = menu.Add(0, 1, 1, "Exit");
|
||||||
|
exitItem.SetIcon(Android.Resource.Drawable.IcMenuCloseClearCancel);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool OnOptionsItemSelected(IMenuItem item)
|
||||||
|
{
|
||||||
|
switch (item.Title.ToS())
|
||||||
|
{
|
||||||
|
case "Config":
|
||||||
|
var intent = new Intent();
|
||||||
|
intent.SetClassName(this, ConfigActivity.ClassName);
|
||||||
|
StartActivityForResult(intent, 0);
|
||||||
|
return true;
|
||||||
|
case "Exit":
|
||||||
|
Finish();
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return base.OnOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void listView_ItemClick(object sender, ItemEventArgs e)
|
private void listView_ItemClick(object sender, ItemEventArgs e)
|
||||||
{
|
{
|
||||||
var intent = new Intent();
|
var intent = new Intent();
|
||||||
|
|
|
@ -6,7 +6,7 @@ namespace MonoStockPortfolio.Activites
|
||||||
{
|
{
|
||||||
public static string ClassName { get { return "monostockportfolio.activites.MainActivity"; } }
|
public static string ClassName { get { return "monostockportfolio.activites.MainActivity"; } }
|
||||||
|
|
||||||
protected Button AddPortfolioButton { get { return FindViewById<Button>(Resource.id.btnAddPortfolio); } }
|
protected Button AddPortfolioButton { get { return FindViewById<Button>(Resource.Id.btnAddPortfolio); } }
|
||||||
protected ListView PortfolioListView { get { return FindViewById<ListView>(Resource.id.portfolioList); } }
|
protected ListView PortfolioListView { get { return FindViewById<ListView>(Resource.Id.portfolioList); } }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -27,7 +27,7 @@ namespace MonoStockPortfolio.Activites
|
||||||
{
|
{
|
||||||
base.OnCreate(bundle);
|
base.OnCreate(bundle);
|
||||||
|
|
||||||
SetContentView(Resource.layout.portfolio);
|
SetContentView(Resource.Layout.portfolio);
|
||||||
|
|
||||||
Refresh();
|
Refresh();
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ namespace MonoStockPortfolio.Activites
|
||||||
public override bool OnCreateOptionsMenu(IMenu menu)
|
public override bool OnCreateOptionsMenu(IMenu menu)
|
||||||
{
|
{
|
||||||
var item = menu.Add(0,1,1,"Refresh");
|
var item = menu.Add(0,1,1,"Refresh");
|
||||||
item.SetIcon(Resource.drawable.ic_menu_refresh);
|
item.SetIcon(Resource.Drawable.ic_menu_refresh);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +115,7 @@ namespace MonoStockPortfolio.Activites
|
||||||
|
|
||||||
private void ShowMessage(string message)
|
private void ShowMessage(string message)
|
||||||
{
|
{
|
||||||
var listAdapter = new ArrayAdapter<string>(this, Android.R.Layout.SimpleListItem1, new[] {message});
|
var listAdapter = new ArrayAdapter<string>(this, Android.Resource.Layout.SimpleListItem1, new[] { message });
|
||||||
QuoteListview.Adapter = listAdapter;
|
QuoteListview.Adapter = listAdapter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,10 +134,10 @@ namespace MonoStockPortfolio.Activites
|
||||||
var textItem = new TextView(this);
|
var textItem = new TextView(this);
|
||||||
textItem.Text = stockDataItem.GetStringValue();
|
textItem.Text = stockDataItem.GetStringValue();
|
||||||
textItem.SetWidth(cellwidth);
|
textItem.SetWidth(cellwidth);
|
||||||
textItem.SetTextColor(Resources.GetColor(Android.R.Color.Black));
|
textItem.SetTextColor(Resources.GetColor(Android.Resource.Color.Black));
|
||||||
QuoteListviewHeader.AddView(textItem);
|
QuoteListviewHeader.AddView(textItem);
|
||||||
}
|
}
|
||||||
QuoteListviewHeader.SetBackgroundResource(Android.R.Color.BackgroundLight);
|
QuoteListviewHeader.SetBackgroundResource(Android.Resource.Color.BackgroundLight);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PositionArrayAdapter : GenericArrayAdapter<PositionResultsViewModel>
|
public class PositionArrayAdapter : GenericArrayAdapter<PositionResultsViewModel>
|
||||||
|
|
|
@ -9,8 +9,8 @@ namespace MonoStockPortfolio.Activites
|
||||||
public static string Extra_PortfolioID { get { return "monoStockPortfolio.PortfolioActivity.PortfolioID"; } }
|
public static string Extra_PortfolioID { get { return "monoStockPortfolio.PortfolioActivity.PortfolioID"; } }
|
||||||
public long ThisPortofolioId { get { return Intent.GetLongExtra(Extra_PortfolioID, -1); } }
|
public long ThisPortofolioId { get { return Intent.GetLongExtra(Extra_PortfolioID, -1); } }
|
||||||
|
|
||||||
protected ListView QuoteListview { get { return FindViewById<ListView>(Resource.id.quoteListview); } }
|
protected ListView QuoteListview { get { return FindViewById<ListView>(Resource.Id.quoteListview); } }
|
||||||
protected Button AddPositionButton { get { return FindViewById<Button>(Resource.id.btnAddPosition); } }
|
protected Button AddPositionButton { get { return FindViewById<Button>(Resource.Id.btnAddPosition); } }
|
||||||
protected LinearLayout QuoteListviewHeader { get { return FindViewById<LinearLayout>(Resource.id.quoteHeaderLayout); } }
|
protected LinearLayout QuoteListviewHeader { get { return FindViewById<LinearLayout>(Resource.Id.quoteHeaderLayout); } }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -5,18 +5,18 @@ namespace MonoStockPortfolio.Framework
|
||||||
{
|
{
|
||||||
public class IoCAttribute : LocationInterceptionAspect
|
public class IoCAttribute : LocationInterceptionAspect
|
||||||
{
|
{
|
||||||
public override void OnGetValue(LocationInterceptionArgs args)
|
public sealed override void OnGetValue(LocationInterceptionArgs args)
|
||||||
{
|
{
|
||||||
if (ServiceLocator.Context == null)
|
if (ServiceLocator.Context == null)
|
||||||
{
|
{
|
||||||
var activityContext= (Context)args.Instance;
|
var activityContext = (Context)args.Instance;
|
||||||
ServiceLocator.Context = activityContext.ApplicationContext.ApplicationContext;
|
ServiceLocator.Context = activityContext.ApplicationContext.ApplicationContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
var locationType = args.Location.LocationType;
|
var locationType = args.Location.LocationType;
|
||||||
var instantiation = ServiceLocator.Get(locationType);
|
var instantiation = ServiceLocator.Get(locationType);
|
||||||
|
|
||||||
if(instantiation != null)
|
if (instantiation != null)
|
||||||
{
|
{
|
||||||
args.SetNewValue(instantiation);
|
args.SetNewValue(instantiation);
|
||||||
}
|
}
|
||||||
|
|
104
MonoStockPortfolio/Framework/IttyBittyIoC.cs
Normal file
104
MonoStockPortfolio/Framework/IttyBittyIoC.cs
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace MonoStockPortfolio.Framework
|
||||||
|
{
|
||||||
|
public static class IttyBittyIoC
|
||||||
|
{
|
||||||
|
[AttributeUsage(AttributeTargets.Constructor)]
|
||||||
|
public class InjectionConstructorAttribute : Attribute
|
||||||
|
{ }
|
||||||
|
|
||||||
|
private enum DependencyType
|
||||||
|
{
|
||||||
|
None = 0, // Type is unset
|
||||||
|
Delegate, // A builder function
|
||||||
|
Instance, // A specific instance
|
||||||
|
Singleton, // Dynamically created singleton
|
||||||
|
Transient // Dynamically created transient object
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DependencyInfo
|
||||||
|
{
|
||||||
|
public object Dependency { get; private set; }
|
||||||
|
public DependencyType DependencyType { get; private set; }
|
||||||
|
|
||||||
|
public DependencyInfo(DependencyType dependencyType, object dependency)
|
||||||
|
{
|
||||||
|
DependencyType = dependencyType;
|
||||||
|
Dependency = dependency;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly static IDictionary<Type, DependencyInfo> dependencies = new Dictionary<Type, DependencyInfo>();
|
||||||
|
private readonly static IDictionary<Type, object> instances = new Dictionary<Type, object>();
|
||||||
|
|
||||||
|
public static void Register<TContract>(TContract instance)
|
||||||
|
{
|
||||||
|
dependencies[typeof(TContract)] = new DependencyInfo(DependencyType.Instance, instance);
|
||||||
|
instances[typeof(TContract)] = instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Register<TContract, TImplementation>()
|
||||||
|
{
|
||||||
|
Register<TContract, TImplementation>(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Register<TContract, TImplementation>(bool isSingleton)
|
||||||
|
{
|
||||||
|
DependencyType dependencyType = isSingleton ? DependencyType.Singleton : DependencyType.Transient;
|
||||||
|
dependencies[typeof(TContract)] = new DependencyInfo(dependencyType, typeof(TImplementation));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Register<TContract>(Func<TContract> builder)
|
||||||
|
{
|
||||||
|
dependencies[typeof(TContract)] = new DependencyInfo(DependencyType.Delegate, builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TContract Resolve<TContract>()
|
||||||
|
{
|
||||||
|
return (TContract)Resolve(typeof(TContract));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static object Resolve(Type contract)
|
||||||
|
{
|
||||||
|
if (!dependencies.ContainsKey(contract))
|
||||||
|
throw new InvalidOperationException(string.Format("Unable to resolve type '{0}'.", contract));
|
||||||
|
if (instances.ContainsKey(contract))
|
||||||
|
return instances[contract];
|
||||||
|
var dependency = dependencies[contract];
|
||||||
|
if (dependency.DependencyType == DependencyType.Delegate)
|
||||||
|
return ((Delegate)dependency.Dependency).DynamicInvoke();
|
||||||
|
|
||||||
|
var constructorInfo = ((Type)dependency.Dependency).GetConstructors()
|
||||||
|
.OrderByDescending(o => (o.GetCustomAttributes(typeof(InjectionConstructorAttribute), false).Count()))
|
||||||
|
.ThenByDescending(o => (o.GetParameters().Length))
|
||||||
|
.First();
|
||||||
|
var parameterInfos = constructorInfo.GetParameters();
|
||||||
|
|
||||||
|
object instance;
|
||||||
|
if (parameterInfos.Length == 0)
|
||||||
|
{
|
||||||
|
instance = Activator.CreateInstance((Type)dependency.Dependency);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var parameters = new List<object>(parameterInfos.Length);
|
||||||
|
foreach (ParameterInfo parameterInfo in parameterInfos)
|
||||||
|
{
|
||||||
|
parameters.Add(Resolve(parameterInfo.ParameterType));
|
||||||
|
}
|
||||||
|
instance = constructorInfo.Invoke(parameters.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dependency.DependencyType == DependencyType.Singleton)
|
||||||
|
{
|
||||||
|
instances[contract] = instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,35 +4,25 @@ using MonoStockPortfolio.Core.Config;
|
||||||
using MonoStockPortfolio.Core.PortfolioRepositories;
|
using MonoStockPortfolio.Core.PortfolioRepositories;
|
||||||
using MonoStockPortfolio.Core.Services;
|
using MonoStockPortfolio.Core.Services;
|
||||||
using MonoStockPortfolio.Core.StockData;
|
using MonoStockPortfolio.Core.StockData;
|
||||||
using TinyIoC;
|
|
||||||
|
|
||||||
namespace MonoStockPortfolio.Framework
|
namespace MonoStockPortfolio.Framework
|
||||||
{
|
{
|
||||||
public static class ServiceLocator
|
public static class ServiceLocator
|
||||||
{
|
{
|
||||||
public static Context Context { get; set; }
|
public static Context Context { get; set; }
|
||||||
private static TinyIoCContainer _container;
|
|
||||||
|
static ServiceLocator()
|
||||||
|
{
|
||||||
|
//IttyBittyIoC.Register(Context);
|
||||||
|
IttyBittyIoC.Register<IStockDataProvider>(() => new GoogleStockDataProvider());
|
||||||
|
IttyBittyIoC.Register<IPortfolioService>(() => new PortfolioService(new AndroidSqlitePortfolioRepository(Context), new GoogleStockDataProvider()));
|
||||||
|
IttyBittyIoC.Register<IPortfolioRepository>(() => new AndroidSqlitePortfolioRepository(Context));
|
||||||
|
IttyBittyIoC.Register<IConfigRepository>(() => new AndroidSqliteConfigRepository(Context));
|
||||||
|
}
|
||||||
|
|
||||||
public static object Get(Type serviceType)
|
public static object Get(Type serviceType)
|
||||||
{
|
{
|
||||||
if (_container == null)
|
return IttyBittyIoC.Resolve(serviceType);
|
||||||
{
|
|
||||||
_container = RegisterTypes();
|
|
||||||
}
|
|
||||||
return _container.Resolve(serviceType);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static TinyIoCContainer RegisterTypes()
|
|
||||||
{
|
|
||||||
var container = TinyIoCContainer.Current;
|
|
||||||
|
|
||||||
container.Register<Context>(Context);
|
|
||||||
container.Register<IStockDataProvider, YahooStockDataProvider>().AsMultiInstance();
|
|
||||||
container.Register<IPortfolioService, PortfolioService>().AsMultiInstance();
|
|
||||||
container.Register<IPortfolioRepository, AndroidSqlitePortfolioRepository>().AsMultiInstance();
|
|
||||||
container.Register<IConfigRepository, AndroidSqliteConfigRepository>().AsMultiInstance();
|
|
||||||
|
|
||||||
return container;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -40,7 +40,7 @@
|
||||||
<Reference Include="mscorlib" />
|
<Reference Include="mscorlib" />
|
||||||
<Reference Include="PostSharp.SL, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b13fd38b8f9c99d7, processorArchitecture=MSIL">
|
<Reference Include="PostSharp.SL, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b13fd38b8f9c99d7, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\libs\PostSharp.SL.dll</HintPath>
|
<HintPath>..\..\..\Program Files (x86)\PostSharp 2.0\Reference Assemblies\Silverlight 3.0\PostSharp.SL.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
|
@ -48,6 +48,7 @@
|
||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="Activites\ConfigActivity.cs" />
|
||||||
<Compile Include="Activites\EditPositionActivity.designer.cs">
|
<Compile Include="Activites\EditPositionActivity.designer.cs">
|
||||||
<DependentUpon>EditPositionActivity.cs</DependentUpon>
|
<DependentUpon>EditPositionActivity.cs</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
@ -58,7 +59,6 @@
|
||||||
<Compile Include="Framework\ActivityExtensions.cs" />
|
<Compile Include="Framework\ActivityExtensions.cs" />
|
||||||
<Compile Include="Framework\ContextExtensions.cs" />
|
<Compile Include="Framework\ContextExtensions.cs" />
|
||||||
<Compile Include="Framework\GenericArrayAdapter.cs" />
|
<Compile Include="Framework\GenericArrayAdapter.cs" />
|
||||||
<Compile Include="Framework\IoCAttribute.cs" />
|
|
||||||
<Compile Include="Activites\MainActivity.designer.cs">
|
<Compile Include="Activites\MainActivity.designer.cs">
|
||||||
<DependentUpon>MainActivity.cs</DependentUpon>
|
<DependentUpon>MainActivity.cs</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
@ -68,17 +68,16 @@
|
||||||
<Compile Include="Activites\PortfolioActivity.designer.cs">
|
<Compile Include="Activites\PortfolioActivity.designer.cs">
|
||||||
<DependentUpon>PortfolioActivity.cs</DependentUpon>
|
<DependentUpon>PortfolioActivity.cs</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="Framework\IoCAttribute.cs" />
|
||||||
|
<Compile Include="Framework\IttyBittyIoC.cs" />
|
||||||
<Compile Include="Framework\ServiceLocator.cs" />
|
<Compile Include="Framework\ServiceLocator.cs" />
|
||||||
<Compile Include="Framework\TinyIoC.cs" />
|
|
||||||
<Compile Include="Resources\Resource.Designer.cs" />
|
<Compile Include="Resources\Resource.Designer.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="Framework\StringExtensions.cs" />
|
<Compile Include="Framework\StringExtensions.cs" />
|
||||||
<Compile Include="Framework\FormValidator.cs" />
|
<Compile Include="Framework\FormValidator.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="PostSharp.Custom.targets">
|
<None Include="PostSharp.Custom.targets" />
|
||||||
<SubType>Designer</SubType>
|
|
||||||
</None>
|
|
||||||
<None Include="Resources\AboutResources.txt" />
|
<None Include="Resources\AboutResources.txt" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -117,15 +116,27 @@
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</AndroidResource>
|
</AndroidResource>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<AndroidResource Include="Resources\layout\config.xml" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup />
|
||||||
|
<ItemGroup>
|
||||||
|
<AndroidResource Include="Resources\drawable-hdpi\ic_menu_refresh.png" />
|
||||||
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<AndroidResource Include="Resources\drawable-hdpi\icon.png" />
|
<AndroidResource Include="Resources\drawable-hdpi\icon.png" />
|
||||||
<AndroidResource Include="Resources\drawable-ldpi\icon.png" />
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<AndroidResource Include="Resources\drawable-mdpi\ic_menu_refresh.png" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
<AndroidResource Include="Resources\drawable-mdpi\icon.png" />
|
<AndroidResource Include="Resources\drawable-mdpi\icon.png" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<AndroidResource Include="Resources\drawable-hdpi\ic_menu_refresh.png" />
|
|
||||||
<AndroidResource Include="Resources\drawable-ldpi\ic_menu_refresh.png" />
|
<AndroidResource Include="Resources\drawable-ldpi\ic_menu_refresh.png" />
|
||||||
<AndroidResource Include="Resources\drawable-mdpi\ic_menu_refresh.png" />
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<AndroidResource Include="Resources\drawable-ldpi\icon.png" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildExtensionsPath)\Novell\Novell.MonoDroid.CSharp.targets" />
|
<Import Project="$(MSBuildExtensionsPath)\Novell\Novell.MonoDroid.CSharp.targets" />
|
||||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
|
|
27
MonoStockPortfolio/Resources/Resource.Designer.cs
generated
27
MonoStockPortfolio/Resources/Resource.Designer.cs
generated
|
@ -15,15 +15,15 @@ namespace MonoStockPortfolio
|
||||||
public partial class Resource
|
public partial class Resource
|
||||||
{
|
{
|
||||||
|
|
||||||
public partial class attr
|
public partial class Attribute
|
||||||
{
|
{
|
||||||
|
|
||||||
private attr()
|
private Attribute()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class drawable
|
public partial class Drawable
|
||||||
{
|
{
|
||||||
|
|
||||||
// aapt resource value: 0x7f020000
|
// aapt resource value: 0x7f020000
|
||||||
|
@ -32,12 +32,12 @@ namespace MonoStockPortfolio
|
||||||
// aapt resource value: 0x7f020001
|
// aapt resource value: 0x7f020001
|
||||||
public const int icon = 2130837505;
|
public const int icon = 2130837505;
|
||||||
|
|
||||||
private drawable()
|
private Drawable()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class id
|
public partial class Id
|
||||||
{
|
{
|
||||||
|
|
||||||
// aapt resource value: 0x7f050004
|
// aapt resource value: 0x7f050004
|
||||||
|
@ -73,12 +73,12 @@ namespace MonoStockPortfolio
|
||||||
// aapt resource value: 0x7f05000a
|
// aapt resource value: 0x7f05000a
|
||||||
public const int quoteListview = 2131034122;
|
public const int quoteListview = 2131034122;
|
||||||
|
|
||||||
private id()
|
private Id()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class layout
|
public partial class Layout
|
||||||
{
|
{
|
||||||
|
|
||||||
// aapt resource value: 0x7f030000
|
// aapt resource value: 0x7f030000
|
||||||
|
@ -88,17 +88,20 @@ namespace MonoStockPortfolio
|
||||||
public const int addposition = 2130903041;
|
public const int addposition = 2130903041;
|
||||||
|
|
||||||
// aapt resource value: 0x7f030002
|
// aapt resource value: 0x7f030002
|
||||||
public const int main = 2130903042;
|
public const int config = 2130903042;
|
||||||
|
|
||||||
// aapt resource value: 0x7f030003
|
// aapt resource value: 0x7f030003
|
||||||
public const int portfolio = 2130903043;
|
public const int main = 2130903043;
|
||||||
|
|
||||||
private layout()
|
// aapt resource value: 0x7f030004
|
||||||
|
public const int portfolio = 2130903044;
|
||||||
|
|
||||||
|
private Layout()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class @string
|
public partial class String
|
||||||
{
|
{
|
||||||
|
|
||||||
// aapt resource value: 0x7f040001
|
// aapt resource value: 0x7f040001
|
||||||
|
@ -107,7 +110,7 @@ namespace MonoStockPortfolio
|
||||||
// aapt resource value: 0x7f040000
|
// aapt resource value: 0x7f040000
|
||||||
public const int hello = 2130968576;
|
public const int hello = 2130968576;
|
||||||
|
|
||||||
private @string()
|
private String()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
9
MonoStockPortfolio/Resources/layout/config.xml
Normal file
9
MonoStockPortfolio/Resources/layout/config.xml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<PreferenceCategory android:title="General Settings">
|
||||||
|
<Preference
|
||||||
|
android:title="Stock Items"
|
||||||
|
android:summary="Which columns do you want to see?"
|
||||||
|
android:key="customStockItems" />
|
||||||
|
</PreferenceCategory>
|
||||||
|
</PreferenceScreen>
|
|
@ -4,16 +4,11 @@
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="fill_parent">
|
android:layout_height="fill_parent">
|
||||||
|
|
||||||
<LinearLayout android:layout_width="fill_parent"
|
<Button android:text="Add New Portfolio" android:layout_height="wrap_content"
|
||||||
android:layout_height="fill_parent" android:orientation="vertical">
|
android:layout_width="fill_parent" android:id="@+id/btnAddPortfolio" />
|
||||||
|
|
||||||
<Button android:text="Add New Portfolio" android:layout_height="wrap_content"
|
<ListView android:id="@+id/portfolioList"
|
||||||
android:layout_width="fill_parent" android:id="@+id/btnAddPortfolio" />
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
<ListView android:id="@+id/portfolioList"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="wrap_content" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
BIN
libs/xunit.dll
Normal file
BIN
libs/xunit.dll
Normal file
Binary file not shown.
Loading…
Reference in a new issue