Xamarin public variables in ContentPage - c#

why are the variables I have created null in my ContentPage
ReceiptPage.xaml.cs
using System;
using System.Collections.Generic;
using Xamarin.Forms;
namespace LiquidCalc
public partial class ReceiptPage : ContentPage
{
public string OutAromaProp { get; set; }
public string OutShotProp { get; set; }
public string OutBasisProp { get; set; }
public ReceiptPage()
{
InitializeComponent();
BindingContext = this;
OutAroma.Text = "Hallo:"+ OutAromaProp;
}
}
On the MainPage
var page = new ReceiptPage
{
OutAromaProp ="Hallo", //"Aroma: " + AromaOut.ToString() + " ml",
OutShotProp = "Nikotien Shot " + NikoteinMG.Text + "mg: " + Math.Round(NikoteinShot).ToString() + " ml",
OutBasisProp = "Basis: " + Math.Round(Basis).ToString() + "ml",
};
await Navigation.PushModalAsync(page,true);
The label only get the value "Hallo:" the the variable OutAromaProp is not assigned .
why?

ok i have it, it wont work of async reasons.
this one solves my issue
protected override void OnAppearing()
{
base.OnAppearing();
OutAroma.Text = OutAromaProp;
OutShot.Text = OutShotProp;
OutBasis.Text = OutBasisProp;
}

Related

Trouble with Data Binding properties within custom Pin class using Xamarin Forms

I'm having trouble setting the data binding for some custom properties within a custom Pin class using Xamarin forms.
Here is the two custom classes I'm dealing with.
public class CustomPin : Pin
{
public static readonly BindableProperty NameProperty = BindableProperty.Create("Name", typeof(string), typeof(Pin), default(string));
public string Name
{
get { return (string)GetValue(NameProperty); }
set { SetValue(NameProperty, value); }
}
public string Icon { get; set; }
}
public class UserData
{
public string Callsign { get; set; }
public string ID { get; set; }
public string Team { get; set; }
public CustomPin Pin { get; set; }
public Position Position { get; set; }
}
Here is the element that holds the values of my Bindings.
public static UserData myUserData = new UserData
{
Callsign = "User",
Pin = new CustomPin
{
BindingContext = myUserData,
Position = new Position(),
Name = "",
Label = ""
},
Position = new Position(),
};
Here is how I set the bindings
myUserData.Pin.SetBinding(CustomPin.PositionProperty, "Position");
myUserData.Pin.SetBinding(CustomPin.LabelProperty, "Callsign");
myUserData.Pin.SetBinding(CustomPin.NameProperty, "Callsign");
And there is the method I use to debug
Debug.WriteLine
(
myUserData.Pin.Name + " should be " + myUserData.Callsign + "\n" +
myUserData.Pin.Label + " should be " + myUserData.Callsign + "\n" +
myUserData.Pin.Position.Latitude + " should be " + myUserData.Position.Latitude + "\n" +
myUserData.Pin.Position.Longitude + " should be " + myUserData.Position.Longitude + "\n"
);
Here is the output, as you can see it doesn't apply the bindings - however I do use this bindings in other objects (such as Xamarin.Forms.Label) and they work just fine.
should be User
should be User
0 should be 37.63150086
0 should be -122.43626643
Thank you in advance for any help.

How do I populate a string array upon instantiation?

So I have created a class that holds properties for the names of albums, including their genre, name and artist with an array that will hold the track list. When compiled, the properties' default values are replaced however I don't know how to replace the default values for the array - I don't know how to replace the default track listing with new tracks for each album. Thanks.
Here is the CD.cs file:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Exercise_2
{
class Cd
{
string name;
string artist;
string genre;
public string[] tracklist;
public string[] newTracklist;
public string getName()
{
return name;
}
public void setName(string newName)
{
name = newName;
}
public string getArtist()
{
return artist;
}
public void setArtist(string newArtist)
{
artist = newArtist;
}
public string getGenre()
{
return genre;
}
public void setGenre(string newGenre)
{
genre = newGenre;
}
public string[] getTracklist()
{
return tracklist;
}
public void setTracklist(string[] newTracklist)
{
string[] tracklist = newTracklist;
}
public Cd()
{
this.name = "CD Name";
this.artist = "CD Artist";
this.genre = "CD Genre";
this.tracklist = new string[3] { "Track1", "Track2", "Track3" };
this.newTracklist = new string[3] { "newTrack1", "newTrack2", "newTrack3" };
}
}
}
And here is the main.cs file:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Exercise_2
{
class Exercise2
{
static void Main()
{
Cd CD1 = new Cd();
CD1.setName("Kill 'Em All");
CD1.setArtist("Metallica");
CD1.setGenre("Thrash Metal");
Cd CD2 = new Cd();
CD2.setName("Ride The Lightning");
CD2.setArtist("Metallica");
CD2.setGenre("Thrash Metal");
Cd CD3 = new Cd();
CD3.setName("Master Of Puppets");
CD3.setArtist("Metallica");
CD3.setGenre("Thrash Metal");
Console.WriteLine(CD1.getName() + " - " + CD1.getArtist() + " - " + CD1.getGenre() + " - " + CD1.getTracklist());
Console.WriteLine(CD2.getName() + " - " + CD2.getArtist() + " - " + CD2.getGenre());
Console.WriteLine(CD3.getName() + " - " + CD3.getArtist() + " - " + CD3.getGenre());
}
}
}
The problem is your setTracklist method creates a new array every time:
public void setTracklist(string[] newTracklist)
{
string[] tracklist = newTracklist;
}
Instead, you need to set the instance tracklist member:
public void setTracklist(string[] newTracklist)
{
tracklist = newTracklist;
}
One more piece of advice. Don't create methods to get and set properties, it's just unnecessary work. Change:
string name;
string artist;
string genre;
public string[] tracklist;
public string[] newTracklist;
To:
public string Name {get; set;}
public string Artist {get; set;}
public string Genre {get; set;}
public string[] Tracklist {get; set;}
You also might want to change tracklist to a List<String> so you can easily add tracks:
public List<String> Tracklist {get; set;}
If you do this, you can create a Cd instance a lot easier:
var newCD = new Cd
{
Name = "Kill 'Em All",
Artist = "Metallica",
Genre = "Thrash Metal"
};
newCD.Tracklist.Add("Hit the Lights");
newCD.Tracklist.Add("The Four Horsemen");
newCD.Tracklist.Add("Motorbreath");
// etc etc
Update:
Here's the full code, in case something got mixed up. I've also implemented a getTracklist method which returns all the tracks is a comma delimited form.
using System;
using System.Collections.Generic;
class Cd
{
public string Name { get; set; }
public string Artist { get; set; }
public string Genre { get; set; }
public List<string> Tracklist { get; set; }
public Cd()
{
Name = "CD Name";
Artist = "CD Artist";
Genre = "CD Genre";
Tracklist = new List<string>();
}
public string getTracklist()
{
return String.Join(", ", Tracklist);
}
}
public class Exercise2
{
public static void Main()
{
Cd CD1 = new Cd();
CD1.Name = "Kill 'Em All";
CD1.Artist = "Metallica";
CD1.Genre = "Thrash Metal";
CD1.Tracklist.Add("Hit the Lights");
CD1.Tracklist.Add("The Four Horsemen");
CD1.Tracklist.Add("Motorbreath");
Cd CD2 = new Cd();
CD2.Name = "Ride The Lightning";
CD2.Artist = "Metallica";
CD2.Genre = "Thrash Metal";
Cd CD3 = new Cd();
CD3.Name = "Master Of Puppets";
CD3.Artist = "Metallica";
CD3.Genre = "Thrash Metal";
Console.WriteLine(CD1.Name + " - " + CD1.Artist + " - " + CD1.Genre + " - " + CD1.getTracklist());
Console.WriteLine(CD2.Name + " - " + CD2.Artist + " - " + CD2.Genre);
Console.WriteLine(CD3.Name + " - " + CD3.Artist + " - " + CD3.Genre);
}
}
You would just write
CD1.setTrackList(new string[] {"Hit The Lights", "The Four Horsemen", "Motorbreath"});
And your setTrackList should read:
public void setTracklist(string[] newTracklist)
{
tracklist = newTracklist;
}
The way you originally wrote it, you were creating a new array of tracks each time you were setting it, instead of setting the backing property.
However, there is a better way to do this. C# has what's called Auto Properties. They handle all this for you.
public string Name {get; set;}
public string Artist {get; set;}
//.... etc

Results from C# JSON-Deserialization to String

I used json2csharp to generate functions and classes but I am a bloody newbie. What I want is using the Data from the JSON Array and display it in a Textbox.
Here is the Code:
public class Sent_SMS
{
public string status { get; set; }
public string error { get; set; }
public string smslog_id { get; set; }
public string queue { get; set; }
public string to { get; set; }
}
public class RootObject
{
public List<Sent_SMS> data { get; set; }
public object error_string { get; set; }
public int timestamp { get; set; }
}
public void doSendSMS()
{
/* API URLs */
APIURL_Send = "http://ipadressofgateway/playsms/index.php?app=ws&op=pv&h=" + apikey + "&u=" + username + "&to=" + receiver_number + "&msg=" + message; // Sending Message
using (WebClient wc = new WebClient())
{
var json = wc.DownloadString(APIURL_Send);
var SMS_Log = JsonConvert.DeserializeObject<RootObject>(json);
richTextBox3.Text = "SMS has been sent to:" + SMS_Log.data.to + "Status is:" + SMS_Log.data.status;
}
}
But of course.. this does not work cause "SMS_Log.data.to" and "SMS_Log.data.status" is not correct. How to do this right?
Regards
If you're sure there is always exactly one SMS in the response, then change your code to:
richTextBox3.Text = "SMS has been sent to:" + SMS_Log.data[0].to + "Status is:" + SMS_Log.data[0].status;
Otherwise, I'd go for a solution like this:
var text = "";
foreach (var sms in SMS_Log.data) {
text += "SMS has been sent to:" + sms.to + "Status is:" + sms.status + "\n";
}
richTextBox3.Text = text;
SMS_Log.data is a list of Sent_SMS instances, so you'd have to iterate through that list to get each individual message's data.
for(int i=0;i<SMS_Log.data.Count();i++)
{
richTextBox3.Text = "SMS has been sent to:" + SMS_Log.data[i].to + "Status is:" + SMS_Log.data[i].status;
}
Though this would set only the last element as your TextBlock text. Would recommend you to add these into a new List and set this list as a source of GridView or ListView

read column names from sqlite table windows 8 app

I am using SQLite for a data entry windows 8 app I am working on. I can create the db, insert data, retrieve a column count, and read data, but cannot get the column names.
The underlying framework is from this post.
I read about the PRAGMA table_info(table_name); command but I cannot seem to send and read back this query properly. I have been googling for 3 days!
MainPage.xaml.cs:
using SQLite;
using SqlLiteTest.Model;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Windows.Storage;
using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
namespace SqlLiteTest
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
txtPath.Text = ApplicationData.Current.LocalFolder.Path;
}
private async void createDB(object sender, RoutedEventArgs e)
{
// access local folder
var qvLocalFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
try
{
//Create a blank carrier file
StorageFile qvLocalFileCarrier = await qvLocalFolder.CreateFileAsync("qvdbLocal.db", CreationCollisionOption.FailIfExists);
//Write the blank carrier file
await FileIO.WriteTextAsync(qvLocalFileCarrier, "");
}
catch { }
// connect
var path = Windows.Storage.ApplicationData.Current.LocalFolder.Path + #"\qvdbLocal.db";
var db = new SQLiteAsyncConnection(path);
// create table
await db.CreateTableAsync<qvdb>();
// insert data
var insertRecords = new List<qvdb>()
{
new qvdb
{
qvdbRecord = 1,
qvdbNotes = "Notes1",
qvdb001 = "Variable 1.1",
qvdb002 = "Variable 2.1"
},
new qvdb
{
qvdbRecord = 1,
qvdbNotes = "Notes1",
qvdb001 = "Variable 1.1",
qvdb002 = "Variable 2.1"
},
new qvdb
{
qvdbRecord = 1,
qvdbNotes = "Notes1",
qvdb001 = "Variable 1.1",
qvdb002 = "Variable 2.1"
},
};
await db.InsertAllAsync(insertRecords);
// read count
var allUsers = await db.QueryAsync<qvdb>("SELECT * FROM qvdb");
var count = allUsers.Any() ? allUsers.Count : 0;
Debug.WriteLine(count);
}
private async void updateDB(object sender, RoutedEventArgs e)
{
var path = Windows.Storage.ApplicationData.Current.LocalFolder.Path + #"\qvdbLocal.db";
var db = new SQLiteAsyncConnection(path);
var tempCell = db.QueryAsync<qvdb>("UPDATE qvdb SET qvdbNotes ='!##$%$%^^&*()+)(*&^%$##!{:L<>?' WHERE qvdbRecord = 10");
await db.UpdateAsync(tempCell);
}
private async void readDB(object sender, RoutedEventArgs e)
{
var path = Windows.Storage.ApplicationData.Current.LocalFolder.Path + #"\qvdbLocal.db";
var db = new SQLiteAsyncConnection(path);
var query = db.Table<qvdb>();
var result = await query.ToListAsync();
foreach (var item in result)
{
MessageDialog dialog = new MessageDialog(string.Format("{0} {1} {2}", item.qvdbRecord, item.qvdbNotes, item.qvdb001));
await dialog.ShowAsync();
}
}
private void readColNames(object sender, RoutedEventArgs e)
{
}
}
}
qvdb.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SQLite;
namespace SqlLiteTest.Model
{
public class qvdb
{
[PrimaryKey, AutoIncrement]
public int qvdbRecord { get; set; }
[MaxLength(3000)]
public string qvdbNotes { get; set; }
[MaxLength(1000)]
public string qvdb001 { get; set; }
[MaxLength(1000)]
public string qvdb002 { get; set; }
}
}
Thanks CL for the info. I added the class but still do not know how to access them. Some more code...
// this works
// read record count
var allRecords = await db.QueryAsync<qvdb>("SELECT * FROM qvdb");
var countRecords = allRecords.Any() ? allRecords.Count : 0;
this.textboxLog.Text = this.textboxLog.Text + Environment.NewLine + "There are " + countRecords + " records.";
// ??
// read column names
var allColumns = await db.QueryAsync<qvdb>("PRAGMA table_info(qvdb)");
foreach (var item in allColumns) {
//read name
this.textboxLog.Text = this.textboxLog.Text + Environment.NewLine + "columbn names";
}
The records returned by PRAGMA table_info look like this:
public class table_info_record
{
public int cid { get; set; }
public string name { get; set; }
public string type { get; set; }
public int notnull { get; set; }
public string dflt_value { get; set; }
public int pk { get; set; }
}
Use it like this:
db.QueryAsync<table_info_record>("PRAGMA table_info(...)");
o end the loop on CL's advice, this code successfully reads the column names:
// read column names
var query = await db.QueryAsync<table_info_record>("PRAGMA table_info(MY_TABLE_NAME_HERE)");
foreach (var item in query)
{
Debug.WriteLine(string.Format("{0}", item.name) + " is a column.");
}

Getters and Setters, getting multiple fields

public class Teams : INotifyPropertyChanged
{
public string CombinedTeams
{
get
{
return Combined;
}
set
{
{
CombinedTeams += value;
NotifiyPropertyChanged("Combined");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifiyPropertyChanged(string p)
{
if (null != p)
{
PropertyChanged(this, new PropertyChangedEventArgs(p));
}
}
private string Combined
{
get
{
return " " + HomeTeam + " " + HomeScore + " - " + AwayScore + " " + AwayTeam;
}
set
{
{
Combined += value;
}
}
}
public string HomeTeam { get; set; }
public string AwayTeam { get; set; }
public string HomeScore { get; set; }
public string AwayScore { get; set; }
}
I got a problem, when trying combine my strings together and having one LONG string that contains all the values from when I parse my XML I only get the First set of values,
basically I get
Team1 Score1 : Score2 Team2
as opposed to
Team1 Score1 : Score2 Team2 Team3 Score3 : Score4 Team4 Team5 Score5 : Score6 Team6
I am binding my Control to CombinedTeams
could you guys help me out? I just want to store the previous string and then combine the new string with the old one, I cant see it being hard but this is confusing me and reading up on it makes me more confused...
Thanks,
John
Your code concatenates the new value to an empty string (last = "").
You probably want to concatenate to the previous value.
I'm not sure what you are expecting, last is always initialized to "", so the += is irrelevant.
Seems like the class called Teams is really a game?
And I don't think setting HomeTeam, AwayTeam, HomeScore, AwayScore over and over again (and then saving this internally somehow) is a good way to keep track of multiple games.
Why don't you look at using a collection of games?
Try something like this:
In a GamesLib library:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
namespace GamesLib
{
public class Game
{
public string HomeTeam { get; private set; }
public string AwayTeam { get; private set; }
public string HomeScore { get; private set; }
public string AwayScore { get; private set; }
public string Combined
{
get
{
return " " + HomeTeam + " " + HomeScore + " - " + AwayScore + " " + AwayTeam;
}
}
public Game(string HomeTeam, string AwayTeam, string HomeScore, string AwayScore)
{
this.HomeTeam = HomeTeam;
this.HomeScore = HomeScore;
this.AwayTeam = AwayTeam;
this.AwayScore = AwayScore;
}
}
public class Games : List<Game>, INotifyPropertyChanged
{
public string CombinedTeams
{
get
{
var str = "";
foreach (Game g in this)
{
str += g.Combined;
}
return str;
}
}
public new void Add(Game g)
{
base.Add(g);
if ( PropertyChanged != null ) {
PropertyChanged(this, new PropertyChangedEventArgs("CombinedTeams"));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
In a console program:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GamesLib;
namespace TestHarness
{
class Program
{
static void Main(string[] args)
{
var gs = new GamesLib.Games();
gs.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(gs_PropertyChanged);
var g = new Game("hometeam", "awayteam", "1", "0");
gs.Add(g);
g = new Game("lions", "bears", "1", "0");
gs.Add(g);
Console.WriteLine("Final result:" + gs.CombinedTeams);
}
static void gs_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
var gs = sender as Games;
Console.WriteLine("Changed: " + gs.CombinedTeams);
}
}
}
The reason you are getting the incorrect results is because you have one property referring to another property, and the second property always returns a specific value.
This block of code, when called from elsewhere, will return the results of some other variable called "Combined" which you have defined below...
public string CombinedTeams
{
get
{
return Combined;
}
...
}
private string Combined
{
get
{
return " " + HomeTeam + " " + HomeScore + " - " + AwayScore + " " + AwayTeam;
}
...
}
Everything else is academic because you're getter(s) essentially always return " " + HomeTeam + " " + HomeScore + " - " + AwayScore + " " + AwayTeam.
I suspect you will want to restructure your code to be something more like this
public class Teams : INotifyPropertyChanged
{
private string Combined; // Backing for CombinedTeams
public string CombinedTeams
{
get
{
return Combined;
}
set
{
// This only concatinates values; Combined will get longer each time.
Combined += value;
// ViewModels should always notify after the vale has changed
NotifyOfPropertyChange("CombinedTeams");
}
}
// Adds a new team, assuming HomeTeam, HomeScore, AwayScore, and AwayTeam have been initialized
public void AddTeam()
{
CombinedTeams = " " + HomeTeam + " " + HomeScore + " - " + AwayScore + " " + AwayTeam;
}
}
Certainly there are better ways to do that, but that should get you a start, I hope.
General rule (broken all the time by the code-ninjas, which is fine) is that a Property shouldn't do any calculations of it's own, it's really there to allow public access to private data in the class.
It might be worthwhile to run through a couple of articles on C# Properties. Here are some suggestions to get you started: http://msdn.microsoft.com/en-us/library/x9fsa0sw(v=vs.80).aspx and http://msdn.microsoft.com/en-us/library/aa288470(v=vs.71).aspx and of course, some Good Search Results

Categories