Xamarin Syncfusion chart not displaying binding data from local database - xamarin.forms

I'm trying to pull data from a local database and populate it in a bar or line chart, I've followed every tutorial out there but can't find where I'm going wrong. The database has data and I can access it with the method App.Database.GetJournalEntries() in other pages and foreach looping through the List, but I can't seem to bind it to the XBindingPath and YBindingPath when I try to use the same list in a chart.
viewData.xaml.cs
public ViewData()
{
InitializeComponent();
this.Title = "Data";
InitializeComponent();
SfChart chart = new SfChart();
chart.Title.Text = "Chart";
//Initializing primary axis
CategoryAxis primaryAxis = new CategoryAxis();
primaryAxis.Title.Text = "Name";
chart.PrimaryAxis = primaryAxis;
//Initializing secondary Axis
NumericalAxis secondaryAxis = new NumericalAxis();
secondaryAxis.Title.Text = "Height (in cm)";
chart.SecondaryAxis = secondaryAxis;
//Initializing column series
ColumnSeries series = new ColumnSeries();
series.ItemsSource = App.Database.GetJournalEntries();
series.XBindingPath = "entryTitle";
series.YBindingPath = "emotRange";
series.Label = "emot";
series.DataMarker = new ChartDataMarker();
series.EnableTooltip = true;
chart.Legend = new ChartLegend();
chart.Series.Add(series);
this.Content = chart;
}
Viewmodel
public class Database
{
SQLiteAsyncConnection _database;
public Database(string dbPath)
{
_database = new SQLiteAsyncConnection(dbPath);
_database.CreateTableAsync<db_GS>().Wait();
}
//Method I'm using to pull the data
public Task<List<db_GS>> GetJournalEntries()
{
return _database.Table<db_GS>().ToListAsync();
}
}
Data model
public class db_GS
{
[PrimaryKey, AutoIncrement]
public int ID { get; set; }
public string entryTitle { get; set; }
public string entryText { get; set; }
public string emot { get; set; }
public float emotRange { get; set; }
public string dataTime { get; set; }
}

Related

Passing lists to the view .Net Core

Im looping through all the results from the SQL query in a .Net Core project. here is Model
public class Mymessagesinfo
{
public int MyMessagesCount { get; set; }
public List<int> MessagesIDs { get; set; }
public List<int> MessagesSendersid { get; set; }
public List<string> MessagesSenders { get; set; }
public List<string> MessagesTitles { get; set; }
public List<string> MessagesInformation { get; set; }
public List<string> MessagesStatus { get; set; }
}
I loop through the users messages in my controller then i pass that model to the view
sqlcon.Open();
int? userid = HttpContext.Session.GetInt32("UserID");
SqlCommand sqlcom = new SqlCommand("select * from messages where Messagereceiver=" +userid , sqlcon);
SqlDataReader reader = sqlcom.ExecuteReader();
if(reader.HasRows)
{
int index = 0;
while(reader.Read())
{
string s;
s = reader[0].ToString();
Mymessages.MessagesIDs.Add(int.Parse(s));
Mymessages.MessagesSendersid.Add(int.Parse(reader[1].ToString()));
Mymessages.MessagesTitles.Add(reader[3].ToString());
Mymessages.MessagesInformation.Add(reader[4].ToString());
Mymessages.MessagesStatus.Add(reader[5].ToString());
index++;
}
Mymessages.MyMessagesCount = index;
}
the very first line Mymessages.MessagesIDs.Add(int.Parse(s)); it throws an exception saying System.NullReferenceException: 'Object reference not set to an instance of an object
i wanted to make sure that reader was holding the results so i added int s and checked on it and it was holding the value it was supposed to.
whats going wrong here? is this how we are supposed to pass list-like data to the view?
You need to initlize MessagesIDs in entity Mymessages, like this:
var Mymessages = new Mymessagesinfo()
{
MessagesIDs = new List<int>()
};
Mymessages.MessagesIDs.Add(id);
Or just define the class like this,
public class Mymessagesinfo
{
public int MyMessagesCount { get; set; }
public List<int> MessagesIDs { get; set; } = new List<int>();
public List<int> MessagesSendersid { get; set; } = new List<int>();
public List<string> MessagesSenders { get; set; } = new List<string>();
public List<string> MessagesTitles { get; set; } = new List<string>();
public List<string> MessagesInformation { get; set; } = new List<string>();
public List<string> MessagesStatus { get; set; } = new List<string>();
}
Here is how I would restructure what you have to make it work.
First, your model class:
public class Mymessagesinfo
{
public List<MessageInfo> Messages { get; set; } = new List<MessageInfo>();
}
public class MessageInfo
{
public int ID { get; set; }
public int Senderid { get; set; }
public string Sender { get; set; }
public string Title { get; set; }
public string Information { get; set; }
public string Status { get; set; }
}
With this approach you have a list of message objects, instead of a bunch of lists containing property data.
Here is how I would suggest you load it from SQL Server:
var data = new Mymessagesinfo();
int? userid = HttpContext.Session.GetInt32("UserID");
var messagesTable = new System.Data.DataTable("messages");
using (var sqlcom = sqlcon.CreateCommand())
{
sqlcom.CommandText = $"select * from messages where Messagereceiver='{userid}'";
using (var adapter = new SqlDataAdapter(sqcom))
{
adapter.Fill(messagesTable);
}
}
// we are now done with SQL and have the data in memory...
foreach(DataRow row in messagesTable.Rows)
{
data.Messages.Add( new MessageInfo {
ID = row.Field<int>(0),
Senderid = row.Field<int>(1),
Sender = row.Field<string>(2),
Title = row.Field<string>(3),
Information = row.Field<string>(4),
Status = row.Field<string>(5),
});
}
return View(data);
This is a lot cleaner and by using a DataAdapter and DataTable you minimize the amount of time that the connection to the database is connected.
Here is how you would use this model in an MVC View:
#Model Mymessagesinfo
<div>
<!-- This is where you can display the properties of the message. //-->
<ul>
#foreach(var message in Model.Messages)
{
<li> #message.Title - #message.Id </li>
}
<ul>
<div>

Null exception when try to display data from viewmodel in view ASP.NET MVC

I am trying to display data in my view using a ViewModel however I am getting null exceptions when doing so and I am not sure what the issue is. Basically I have a user, who's data I wish to display in a profile layout in my view, as well as data from different tables all in the same profile view.
ViewModel Code:
public int DonatorID { get; set; }
public string DonatorName { get; set; }
public string DonatorSurname { get; set; }
public string DonatorEmail { get; set; }
public int ContactNo { get; set; }
public int UserID { get; set; }
public string DonatorRank { get; set; }
public string RankIcon { get; set; }
public int XpAmount { get; set; }
public int TokenBalance { get; set; }
public int PaymentID { get; set; }
public string CardNo { get; set; }
public int ExpirationMonth { get; set; }
public int ExpirationYear { get; set; }
public int CVV { get; set; }
public int Zip { get; set; }
public string CardType { get; set; }
public int PaymentDonatorID { get; set; }
public int NpoID { get; set; }
public string NpoName { get; set; }
public double Longitude { get; set; }
public double Latitude { get; set; }
Controller Code:
id = 1;
//Disable lazy loading
db.Configuration.ProxyCreationEnabled = false;
//Add data to the dynamic object
var DynamicProfileDetail = db.tblDonator.Where(zz => zz.user_id == id).Include(yy => yy.tblUser).Include(xx => xx.tblDonator_Rank).FirstOrDefault();
DonatorUserViewModel ProfileDetails = new DonatorUserViewModel();
//Set profile details values
ProfileDetails.DonatorName = DynamicProfileDetail.donator_name;
ProfileDetails.DonatorSurname = DynamicProfileDetail.donator_surname;
ProfileDetails.DonatorEmail = DynamicProfileDetail.tblUser.email;
ProfileDetails.ContactNo = Convert.ToInt32(DynamicProfileDetail.donator_contact_no);
//Set other information
ProfileDetails.XpAmount = DynamicProfileDetail.xp_amount;
ProfileDetails.DonatorRank = DynamicProfileDetail.tblDonator_Rank.description;
ProfileDetails.RankIcon = DynamicProfileDetail.tblDonator_Rank.rank_icon;
ProfileDetails.TokenBalance = DynamicProfileDetail.donator_token_balance;
//Payment details section
int DonatorID = DynamicProfileDetail.donator_id;
var DynamicPaymentDetails = db.tblDonator_Payment_Details.Where(gg => gg.donator_id == DonatorID).Include(ff => ff.tblCard_Type).FirstOrDefault();
DonatorUserViewModel PaymentDetails = new DonatorUserViewModel();
//Set payment detail values
PaymentDetails.CardNo = DynamicPaymentDetails.donator_card_no;
PaymentDetails.ExpirationMonth = DynamicPaymentDetails.expiration_month;
PaymentDetails.ExpirationYear = DynamicPaymentDetails.expiration_year;
PaymentDetails.CVV = DynamicPaymentDetails.cvv;
PaymentDetails.Zip = DynamicPaymentDetails.zip_code;
PaymentDetails.CardType = DynamicPaymentDetails.tblCard_Type.description;
//Map marker section
var DynamicMapMarkers = db.tblNpo;
DonatorUserViewModel MapMarkers = new DonatorUserViewModel();
//Set map marker values
foreach (var item in DynamicMapMarkers)
{
MapMarkers.NpoID = item.npo_id;
MapMarkers.NpoName = item.npo_name;
MapMarkers.Longitude = Convert.ToDouble(item.longitude);
MapMarkers.Latitude = Convert.ToDouble(item.latitude);
MapMarkerList.Add(MapMarkers);
}
//ViewBags to display the relevant info
ViewBag.MapMarkerList = MapMarkerList;
return View();
My logic in the code above is that I am setting the values from my database to the objects in the ViewModel and then would be able to display it in my view.
View Code:
#model MyProject.ViewModels.DonatorUserViewModel
<h2>View/Edit your Details:</h2>
<ul>
<li>First Name: #Model.DonatorName</li>
<li>Surname: #Model.DonatorSurname</li>
<li>Contact Number: #Model.ContactNo</li>
<li>Email Address: #Model.DonatorEmail</li>
</ul>
Sorry for the amount of code in the question (particulary the viewmodel and controller sections) I just need to show that there are a lot of different objects from different database tables.
Now back to my issue, I am getting a null exception in my view for <li>First Name: #Model.DonatorName</li> and I'm assuming for the rest of them as well. I have a feeling there is something wrong with the way I am trying to use my viewmodel, as I am used to doing it using lists and then looping through that list in the view, however I am not sure how to do it now that I am only displaying essentially one line from the database tables instead of all the lines. Anyway any help would be much appreciated.

ASP.NET json object doesn't contain custom object

When a user gets to a location, he will get a question. As such, I have a class for "Questions" and a class for "Locations". When I retrieve a location, however, the Question parameter is always null.
This seems to be a problem with the whole project, as the same problem repeats itself somewhere else (here, a "Game" has a list of "Teams", but the teams are always empty).
Objects are created when database is initialized:
public static void Initialize(DBContext context)
{
context.Database.EnsureCreated();
if (!context.Games.Any())
{
var teams = new List<Team>();
var team1 = new Team()
{
TeamName = "Kwizmasterz",
TotalPoints = 0,
TotalBoobyTraps = 2
};
var team2 = new Team()
{
TeamName = "Xesennettet",
TotalPoints = 0,
TotalBoobyTraps = 2
};
teams.Add(team1);
teams.Add(team2);
var game = new Game()
{
GameCode = "X35H0",
team = teams
};
context.Games.Add(game);
context.SaveChanges();
}
if (!context.Locations.Any())
{
var que = new Question()
{
QuestionText = "How much is 2 + 2?",
Answer = "4",
IsSolved = false,
Points = 1000000
};
var loc = new Location()
{
LocationName = "LocationName",
Latitude = 50.2299036,
Longitude = 5.4163052,
Question = que,
IsBoobyTrapped = false
};
context.Locations.Add(loc);
context.SaveChanges();
}
}
Location Class:
public class Location
{
public int LocationID { get; set; }
public string LocationName { get; set; }
public double Latitude { get; set; }
public double Longitude { get; set; }
public Question Question { get; set; }
public bool IsBoobyTrapped { get; set; }
public int VictorTeamID { get; set; } = -1;
}
Question Class:
public class Question
{
public int QuestionID { get; set; }
public int QuestionType { get; set; } // 1 = Question - Answer
public string QuestionText { get; set; }
public int Points { get; set; }
public bool IsSolved { get; set; }
public string Answer { get; set; }
}
Controller Class:
[Route("api/v1")]
public class GameController : Controller
{
private readonly DBContext context;
public GameController(DBContext context)
{
this.context = context;
}
public IActionResult Index()
{
return View();
}
[Route("location")]
[HttpPost]
public IActionResult postGame([FromBody] Location newLocation)
{
newLocation.LocationID = context.Games.Count();
context.Locations.Add(newLocation);
return Created("", newLocation);
}
[Route("location")]
[HttpGet]
public List<Location> getLocations()
{
return context.Locations.ToList();
}
[Route("location/{id}")]
[HttpGet]
public Location getLocation(int id)
{
int _id = id - 1;
List<Location> loc = context.Locations.ToList();
if (loc[_id] != null)
return loc[_id];
else
return null;
}
[Route("game")]
[HttpPost]
public IActionResult postGame([FromBody] Game newGame)
{
newGame.GameID = context.Games.Count();
context.Games.Add(newGame);
return Created("", newGame);
}
[Route("game")]
[HttpGet]
public List<Game> getGames()
{
return context.Games.ToList();
}
[Route("game/{id}")]
[HttpGet]
public Game getGame(int id)
{
List<Game> game = context.Games.ToList();
if (game[id] != null)
return game[id];
else
return null;
}
}
This is because of lazy loading so objects stored in other tables won't load unless you include them.
Link
You can do this by using Include("Question") so the complete syntax would be:
context.Locations.Include("Question") so you will include the question when retrieving the locations
You can do also multiple includes by chaining them context.Locations.Include("Question").Include("SomethingElse")
Edit as i see in your code getLocation still does not use the include. see below for the correct way to use it
public Location getLocation(int id)
{
int _id = id - 1;
List<Location> loc = context.Locations.Include("Question").ToList();
if (loc[_id] != null)
return loc[_id];
else
return null;
}
2nd edit
Also i would rewrite getLocation because your pulling the whole list first and after getting the single location
public Location getLocation(int id)
{
int _id = id - 1;
//FirstOrDefault will return automatically a null if the id cannot be found.
//This will result in only getting the single Location from context instead the complete list
return context.Locations.Include("Question").FirstOrDefault(x=>x.id == _id);
}

UWP Map Control Binding

In my UWP application: I have a SQLite data base with some points and it's coordinates. I am using Entity Framework 7 and I want to bind the data to a map control. Since I only want to keep the coordinates in the database. I created a partial class to add the other required properties to bind to the map:
//Database Fields
public partial class oFeature
{
[Key]
public string idRecord { get; set; }
public string idTag { get; set; }
public Double Latitude { get; set; }
public Double Longitude { get; set; }
public string ImageSourceUri { get; set; }
public string MoreInfo { get; set; }
}
//Binding Required Fields
public partial class oFeature
{
[NotMapped]
public Geopoint Location { get; set; }
[NotMapped]
public Point NormalizedAnchorPoint { get; set; }
[NotMapped]
public Uri UriSourceImage { get; set; }
}
To create the list for the binding I have the following code:
IQueryable<oFeature> myFeatures;
using (var db = new fldContext())
{
myFeatures = from b in db.oFeatures
select new oFeature()
{
idRecord = b.idRecord,
idTag = b.idTag,
Latitude = b.Latitude,
Longitude = b.Longitude,
ImageSourceUri = b.ImageSourceUri,
MoreInfo = b.MoreInfo,
Location = new Geopoint(new BasicGeoposition(){Latitude=b.Latitude,Longitude=b.Longitude}),
NormalizedAnchorPoint = new Point(0.5, 0.5),
UriSourceImage = new Uri("ms-appx:///Assets/green.png")
};
int recount = myFeatures.Count();
var sourceData = myFeatures.ToList();
MapItems.ItemsSource = sourceData;
}
If I remove the location line:
Location = new Geopoint(new BasicGeoposition(){Latitude=b.Latitude,Longitude=b.Longitude})
The code works but of course when I bind to the map I get an error because I have no locations. But If I keep the locations line I get an error at the line:
int recount = myFeatures.Count();
I am getting the following error:
An exception of type 'System.ArgumentNullException' occurred in System.Linq.Expressions.dll but was not handled in user code
Additional information: Value cannot be null.
{"Value cannot be null.\r\nParameter name: constructor"}
Any help would be appreciated.

using DataContractJsonSerializer when Json object propety is named with "#" symbol

When using DataContractJsonSerializer to parse a json response, I've come across a json object with a property name of #id and I can't seem to populate this field. All of the other fields are populated without a problem. I can even get this field populated using Fiddler, but not using DataContractJsonSerializer. My code is as follows...
public IEnumerable<Vehicle> vehicles { get; set; }
public async Task GetVehicleList(string access_token)
{
vehicles = await GetVehicleListInfo(access_token);
}
private async Task<IEnumerable<Vehicle>> GetVehicleListInfo(string access_token)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("https://www.example.com/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/vnd.example.api-v1+json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer" + access_token);
HttpResponseMessage response = await client.GetAsync("vehicles");
//IEnumerable<Vehicle> vehicles = new IEnumerable<Vehicle>();
Vehicle vehicle = new Vehicle();
PagedVehicleResult pvr = new PagedVehicleResult();
Stream dataStream = null;
if (response.IsSuccessStatusCode)
{
dataStream = await response.Content.ReadAsStreamAsync();
DataContractJsonSerializer serializer = new DataContractJsonSerializer(pvr.GetType());
pvr = (PagedVehicleResult)serializer.ReadObject(dataStream);
}
vehicles = pvr.vehicle;
return vehicles;
}
}
}
/// <summary>
/// parent object returned by json. contains list of vehicle objects
/// </summary>
public class PagedVehicleResult
{
public int count { get; set; }
public int index { get; set; }
public int limit { get; set; }
public int total { get; set; }
public string type { get; set; }
public IEnumerable<Vehicle> vehicle { get; set; }
}
public class Vehicle
{
public int id { get; set; } //This is the property in question.
//When it comes back in fiddler it looks like "#id", and it does get populated.
//when it comes back in my console application it is 0 if int and null if string.
public string vin { get; set; }
public string label { get; set; }
public string color { get; set; }
public string make { get; set; }
public string model { get; set; }
public string deviceSerialNumber { get; set; }
public int year { get; set; } //consider making date? unknown repercussions
public CreateTimestamp createdTimestamp { get; set; }
public ModifiedTimestamp modifiedTimestamp { get; set; }
}
public class CreateTimestamp
{
public string readOnly { get; set; }
public string value { get; set; } //had to cast as string.. can convert to datetime before database insert
}
public class ModifiedTimestamp
{
public string readOnly { get; set; }
public string value { get; set; }
}
How can I map that json #id field to my Vehicle class id property?
Okay, I figured this out on my own from reading various different post on the subject.
All I had to do was parse it into a json string first, then call a .replace() on the string to change the id. Then I used the JavaScriptSerializer on that and it worked.
if (response.IsSuccessStatusCode)
{
dataStream = await response.Content.ReadAsStreamAsync();
string content;
using (StreamReader reader = new StreamReader(dataStream, true))
{
content = reader.ReadToEnd();
content = content.Replace("#id", "id");
JavaScriptSerializer js = new JavaScriptSerializer();
pvr = js.Deserialize<PagedVehicleResult>(content);
}
}
vehicles = pvr.vehicle;
return vehicles;
Now, when i try, my object id is correctly inserted.

Resources