Windows Phone 8.1 Currency converter Json - c#

I got a school project. I have to make a currency converter and I got stuck. I found something on the Code Project web site, but I am new at this and I do not really know how to implement it in my project.
I tried something like `
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
this.NavigationCacheMode = NavigationCacheMode.Required;
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
}
class WebClient
{
internal string DownloadString(string url)
{
throw new NotImplementedException();
url = "https://openexchangerates.org/api/latest.json?app_id=ae11142304694b10a1dbf2d25933a333";
var currencyRates = _download_serialized_json_data<App9.CurrencyRates>(url);
}
}
public static T _download_serialized_json_data<T>(string url) where T : new()
{
var w = new WebClient();
{
//using (var w = new WebClient()) {
var json_data = string.Empty;
// attempt to download JSON data as a string
try
{
json_data = w.DownloadString(url);
}
catch (Exception) { }
// if string with JSON data is not empty, deserialize it to class and return its instance
return !string.IsNullOrEmpty(json_data) ? JsonConvert.DeserializeObject<T>(json_data) : new T();
}
}
private void comboBoxTo_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
}
private void convertButton_Click(object sender, RoutedEventArgs e)
{
if (amountTb.Text == string.Empty)
{
afisareTb.Text = "Scrieti o valoare";
}
else
{
var currencyRates = _download_serialized_json_data<CurrencyRates>("https://openexchangerates.org/api/latest.json?app_id=YOUR_APP_ID ");
}
}
}
`
I do not have any errors, it is just that, when I press on converter button from my app, nothing happens.

Related

How to get json response with WebView2

I wanna get a json from the response's body of this API:
// http://localhost:3000/api/auth/[token]
export default function Auth(request, response) {
response.status(200).json({ token: request.query})
}
Trying the WebView.CoreWebView2.WebResourceResponseReceived event fires just once and the event arg's request Uri parameter is "http://localhost:3000/favicon.ico".
How can I get the response content?
What I did:
public partial class SignInUserControl : UserControl
{
public SignInUserControl()
{
InitializeComponent();
InitWebView();
}
async void InitWebView()
{
await WebView.EnsureCoreWebView2Async(null);
WebView.CoreWebView2.WebResourceResponseReceived += CoreWebView2_WebResourceResponseReceived;
}
async void CoreWebView2_WebResourceResponseReceived(object sender, CoreWebView2WebResourceResponseReceivedEventArgs e)
{
try
{
Stream stream = await e.Response.GetContentAsync();
TextReader tr = new StreamReader(stream);
string re = tr.ReadToEnd();
}
catch { }
}
}
What I expect:
http://localhost:3000/api/auth/42sad87aWasFGAS
re = {"token":"42sad87aWasFGAS"} // From CoreWebView2_WebResourceResponseReceived method
ps: The WebViewer2 Control is working. So I don't think the problem is related to its initialization.
working example
The problem really was the WebView initialization. 🤦‍♂️
Thanks to #user09938 and #david-risney
What did I do?
I removed the Source property from the Xaml and made these changes:
public partial class SignInUserControl : UserControl
{
public SignInUserControl()
{
InitializeComponent();
InitwebView();
}
private void InitwebView()
{
WebView.CoreWebView2InitializationCompleted += WebView_CoreWebView2InitializationCompleted;
WebView.EnsureCoreWebView2Async(null).GetAwaiter();
WebView.Source = new Uri("http://localhost:3000/api/auth/NelsonHenrique");
}
private void WebView_CoreWebView2InitializationCompleted(object sender, CoreWebView2InitializationCompletedEventArgs e)
{
WebView.CoreWebView2.WebResourceResponseReceived += CoreWebView2_WebResourceResponseReceived;
}
private void CoreWebView2_WebResourceResponseReceived(object sender, CoreWebView2WebResourceResponseReceivedEventArgs e)
{
var result = e.Response.GetContentAsync().GetAwaiter();
result.OnCompleted(() =>
{
try
{
var res = result.GetResult();
StreamReader reader = new StreamReader(res);
string text = reader.ReadToEnd();
// text: "{\"token\":\"NelsonHenrique\"}"
}
catch (Exception e)
{
Console.WriteLine(e);
}
});
}
}

Passing Object from Class to Windows Form

I've got four main files in play here: Form 1, which is called frmLogin, Form2, which is called frmUserHome, a class called DbConnector.cs and a class called BankAccount.cs
The program works as follows: Form1 calls method from DBConnector -> DB Connector method fills an object and it's variables which is instantiated in DBConnector. This object is of class BankAccount.cs
Then, after the method finishes and if successful, Form1 instantiates Form2 and it opens. In form2 is where I want to access the object that was created in the DBconnector class. How do I do this? I've tried instantiating new objects of BankAccount.cs in there, I've tried all these different constructor stuff I've seen on here. Nothing seems to be working.
For reference: the object is populated when it runs in Dbconnector. However, when I try to receive data when I use it in Form2, all of the fields are NULL.
I've made countless adjustments from reading different posts on here so the code is rightfully a mess now and probably extremely unorganised.
Here's the main portions of my code below:
Form1
namespace BankingSystem
{
public partial class frmLogIn : Form
{
public BankAccount myBankAccount = new BankAccount();
dbConnector newConnector;
public frmLogIn()
{
InitializeComponent();
timerMain.Enabled = true;
timerMain.Start();
}
private void btnLogIn_Click(object sender, EventArgs e)
{
try
{
newConnector.CheckDetailsLogin(accountNumTextBox.Text, pinNumTextBox.Text);
frmUserHome UserHome = new frmUserHome();
MessageBox.Show("Success! Happy Banking!");
UserHome.ShowDialog();
}
catch
{
MessageBox.Show("Failed - incorrect login details.");
}
}
}
}
DBConnector Class:
namespace BankingSystem
{
public class dbConnector
{
Boolean isCorrect = false;
private static SQLiteConnection sqlconnConnection;
public BankAccount myBankAccount = new BankAccount();
public DataSet myAppDataSet = new DataSet(); // created for you to use and push data into
public dbConnector(string strFilePath)
{
try
{
sqlconnConnection = new SQLiteConnection("Data Source=" + strFilePath);
}
catch (Exception ex)
{
throw new Exception("DbConnector initialisation unsuccessful:\n" + ex.Message);
}
}
public void CheckDetailsLogin(string strAccno, string strPin)
{
// this is where check ou the boiler plate code and adjst to my APP.
try
{
DataTable dtUser = new DataTable();
sqlconnConnection.Open();
string strQuery2 = #"SELECT * FROM Accounts WHERE Account_Number='"+ strAccno +"' AND PIN='"+ strPin +"';"; // example of a parametrised SQL statement.
SQLiteCommand sqlcomCommand2 = new SQLiteCommand(strQuery2, sqlconnConnection);
SQLiteDataAdapter sqldatadptAdapter = new SQLiteDataAdapter(sqlcomCommand2); // local SQL data Adaptor
try
{
sqldatadptAdapter.Fill(dtUser);
}
catch (Exception ex)
{
// Exception will the "thrown"/Raised when there was a problem
throw new Exception($"SELECT unsuccessful:\n{ex.Message}");
}
finally
{
sqlconnConnection.Close();
}
if (dtUser.Rows.Count == 0)
{
// the record set comes back with no records found, an empty Datatable with no rows
// means there was no data matching your query
throw new Exception("No Such Bank user found");
}
else
{
// change to your applications needs
// Rows[0] - we are expecting at least 1 row, and its basically an array so we address
// the first element with 0
// Rows[0]["fieldnamefromDB"] <- referencing the column in the DB
//this.strID = strUserID;
myBankAccount.AccountNumber = dtUser.Rows[0]["Account_Number"].ToString();
myBankAccount.AccountPin = dtUser.Rows[0]["PIN"].ToString();
myBankAccount.AccountBalance = Convert.ToDecimal(dtUser.Rows[0]["Balance"]);
myBankAccount.AccountHolder = dtUser.Rows[0]["First_Name"].ToString();
myBankAccount.AccountAddress = dtUser.Rows[0]["Home_Address"].ToString();
myBankAccount.MyAccountGUID = dtUser.Rows[0]["GUID"].ToString();
if (myBankAccount.AccountNumber == strAccno && myBankAccount.AccountPin == strPin)
{
isCorrect = true;
}
else
{
isCorrect = false;
}
//myLocalBankAccUsr
}
}
catch (Exception ex)
{
// exception thrown for the whole method or function
throw new Exception($"User(string):\n{ex.Message}");
}
}
BankAccount.cs class
namespace BankingSystem
{
public class BankAccount
{
private string accountNumber;
private decimal accountBalance;
private string accountHolder;
private string accountPhoneNumber;
private string accountAddress;
private string accountPin;
private string myAccountGUID;
// private string AccountHolderGUID;
// private string AccountTypeGUID;
public string AccountNumber
{
get { return accountNumber; }
set { accountNumber = value; }
}
public decimal AccountBalance
{
get { return accountBalance; }
set { accountBalance = value; }
}
public string AccountHolder
{
get { return accountHolder; }
set { accountHolder = value; }
}
public string AccountPhoneNumber
{
get { return accountPhoneNumber; }
set { accountPhoneNumber = value; }
}
public string AccountAddress
{
get { return accountAddress; }
set { accountAddress = value; }
}
public string AccountPin
{
get { return accountPin; }
set { accountPin = value; }
}
public string MyAccountGUID
{
get { return myAccountGUID; }
set { myAccountGUID = value; }
}
public Boolean CanWithDrawAmount(decimal AmountToTransfer)
{
if (AmountToTransfer > this.AccountBalance){
return false;
}else
{
return true;
}
}
public void UpdatePIN()
{
// connect to bank DB connector
// send it the new pin
// SQL update command
}
}
}
Here is Form2:
namespace BankingSystem
{
public partial class frmUserHome : Form
{
public frmUserHome()
{
InitializeComponent();
tabMainForm.Appearance = TabAppearance.FlatButtons;
tabMainForm.ItemSize = new Size(0, 1);
tabMainForm.SizeMode = TabSizeMode.Fixed;
timerMain.Enabled = true;
timerMain.Start();
}
private void frmUserHome_Load(object sender, EventArgs e)
{
labelWelcome.Text = "Welcome "; //newMainBank.AccountHolder;
}
The 'labelWelcome.Text = "Welcome" is where I want the name stored inside the object to be used. So it should ideally access the BankAccount class, access the AccountHolder field and use that field to concat onto the end of the 'Welcome' text. However, it just shows 'Welcome' and no name on the end, when I run the program (because all values get reset to null in form2.. for some reason)
Below I have updated the code for Form1 and Form2.
Form 1
namespace BankingSystem
{
public partial class frmLogIn : Form
{
dbConnector newConnector;
public frmLogIn()
{
InitializeComponent();
newConnector = new dbConnector(**pass str file path**);
timerMain.Enabled = true;
timerMain.Start();
}
private void btnLogIn_Click(object sender, EventArgs e)
{
try
{
newConnector.CheckDetailsLogin(accountNumTextBox.Text, pinNumTextBox.Text);
frmUserHome UserHome = new frmUserHome(newConnector.myBankAccount);
MessageBox.Show("Success! Happy Banking!");
UserHome.ShowDialog();
}
catch
{
MessageBox.Show("Failed - incorrect login details.");
}
}
}
}
Form 2
namespace BankingSystem
{
public partial class frmUserHome : Form
{ public BankAccount _bankAccount;
public frmUserHome(BankAccount bankAccount)
{
InitializeComponent(); _bankAccount = bankAccount;
tabMainForm.Appearance = TabAppearance.FlatButtons;
tabMainForm.ItemSize = new Size(0, 1);
tabMainForm.SizeMode = TabSizeMode.Fixed;
timerMain.Enabled = true;
timerMain.Start();
}
private void frmUserHome_Load(object sender, EventArgs e)
{
labelWelcome.Text = "Welcome "+ bankAccount.AccountHolder;
}

WPF application doesn't run (or appear) if api not available

I have a simple WPF application that doesn't appear if api is not available. How do I handle it so screen at least shows up saying no api is available?
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
GetWeather();
}
private void GetWeather()
{
using (var client = new WebClient())
{
var content = client.DownloadString($"http://localhost:50054/WeatherForecast");
var data = JsonConvert.DeserializeObject<IEnumerable<WeatherForecast>>(content);
message4Label.Text = data.ToList()[0].Summary;
}
}
}
You must move the call from the constructor of the form because if there's an exception it will close the form without any message. Also, protecting the function with a try/catch is always a good idea.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
public void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
if(!GetWeather())
//Present a message to the user
}
private bool GetWeather()
{
try
{
using (var client = new WebClient())
{
var content = client.DownloadString($"http://localhost:50054/WeatherForecast");
var data = JsonConvert.DeserializeObject<IEnumerable<WeatherForecast>>(content);
message4Label.Text = data.ToList()[0].Summary;
}
return true;
}
catch{ return false; }
}
}

Singleton Bindable Controls While Tasking/Multi-Threading

before posting the question i did my research for 10 days so really hope someone can shed some light into solving this issue.
The issue is that any bindable control, does not update once the binding list from singleton class is changed. This is a common issue on multi-threaded apps. Most if not all solutions offer suggestions where the bindlinglist or collection is initialized from parent thread, and then some invocation to be made. Not what i'm looking for. The same issue persist if static class is used instead of singleton.
Basically, the application triggers some Tasks, which in turn create object(s) on different business classes. These objects post messages into the bindinglist, which should update the UI listbox, but does not. And yes, the message object is in the list, and binding after the TASK finished works (items displayed). Locking/unlocking object(s) access is also not an issue.
Appreciate any suggestions/solutions
A trimmed down version of business objects:
namespace MyNameSpace
{
public class Message
{
private string messageSummary;
public Message() { }
public string MessageSummary
{
set { messageSummary = value; }
get { return messageSummary; }
}
}
}
A trimmed down version of another class doing some ops:
namespace MyNameSpace
{
public class WorkDoingClass
{
public WorkDoingClass() { }
public void DoSomeWork()
{
//some routines
Message messageObj = new Message();
messageObj.MessageSummary = "DoSOmrWork Finished";
}
public void DoSomeOtherWork()
{
//some routines
Message messageObj = new Message();
messageObj.MessageSummary = "DoSomeOtherWork Finished";
AllMessages.Instance.AllMessagesBindingList.Add(messageObj);
}
}
}
Singleton:
namespace MyNameSpace
{
public sealed class AllMessages
{
private static readonly AllMessages _instance = new AllMessages();
private BindingList<Message> _allMessagesBL;
public WorkDoingClass() { _allMessagesBL = new BindingList<Message>(); }
public static AllMessages Instance
{
get { return _instance; }
}
public BindingList<Message> AllMessagesBindingList
{
get { return _allMessagesBL};
}
}
}
This is also a trimmed down version from where calls start:
namespace MyNameSpace
{
public partial class Form1 : Form
{
private Task _TaskSqlData;
private CancellationTokenSource cTokenSourceSql;
public Form1()
{
InitializeComponent();
listBox1.DataSource = AllMessages.Instance.AllMessagesBindingList;
listBox1.DisplayMember = "MessageSummary";
}
private void button1_Click(object sender, EventArgs e)
{
cTokenSourceSql = new CancellationTokenSource();
var tokenSqlData = cTokenSourceSql.Token;
if (this._TaskSqlData != null)
{
if (this._TaskSqlData.Status == TaskStatus.Running)
this.cTokenSourceSql.Cancel();
this._TaskSqlData.Dispose();
this._TaskSqlData = null;
}
_TaskSqlData = Task.Factory.StartNew(()
=> StartDoingWork(this, tokenSqlData, null), tokenSqlData);
}
public void StartDoingWork(object sender, CancellationToken ct, EventArgs e)
{
if (ct.IsCancellationRequested)
ct.ThrowIfCancellationRequested();
WorkDoingClass work = new WorkDoingClass();
work.DoSomeOtherWork();
}
Your problem is that the thread(the main UI thread) making the listbox is different from the thread(the worker thread) modifying the collection.
Try the following code. It could solve your issue. I use SynchronizationContext to synchronize the two threads, which serves as the same function with Control.Invoke().
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
private Task _TaskSqlData;
private CancellationTokenSource cTokenSourceSql;
WorkDoingClass _work;
public Form1()
{
InitializeComponent();
listBox1.DataSource = AllMessages.Instance.AllMessagesBindingList;
listBox1.DisplayMember = "MessageSummary";
_work = new WorkDoingClass(SynchronizationContext.Current);
}
private void button1_Click(object sender, EventArgs e)
{
cTokenSourceSql = new CancellationTokenSource();
var tokenSqlData = cTokenSourceSql.Token;
if (this._TaskSqlData != null)
{
if (this._TaskSqlData.Status == TaskStatus.Running)
this.cTokenSourceSql.Cancel();
this._TaskSqlData.Dispose();
this._TaskSqlData = null;
}
_TaskSqlData = Task.Factory.StartNew(()
=> StartDoingWork(this, tokenSqlData, null), tokenSqlData);
}
public void StartDoingWork(object sender, CancellationToken ct, EventArgs e)
{
if (ct.IsCancellationRequested)
ct.ThrowIfCancellationRequested();
_work.DoSomeOtherWork();
}
}
public class Message
{
private string messageSummary;
public Message() { }
public string MessageSummary
{
set { messageSummary = value; }
get { return messageSummary; }
}
}
public class WorkDoingClass
{
private SynchronizationContext _syncContext;
public WorkDoingClass() { }
public WorkDoingClass(SynchronizationContext _syncContext)
{
// TODO: Complete member initialization
this._syncContext = _syncContext;
}
public void DoSomeWork()
{
//some routines
Message messageObj = new Message();
messageObj.MessageSummary = "DoSOmrWork Finished";
}
public void DoSomeOtherWork()
{
_syncContext.Send(DoWork, null);
}
private static void DoWork(object arg)
{
//some routines
Message messageObj = new Message();
messageObj.MessageSummary = "DoSomeOtherWork Finished";
AllMessages.Instance.AllMessagesBindingList.Add(messageObj);
}
}
public sealed class AllMessages
{
private static readonly AllMessages _instance = new AllMessages();
private BindingList<Message> _allMessagesBL;
public AllMessages() { _allMessagesBL = new BindingList<Message>(); }
public static AllMessages Instance
{
get { return _instance; }
}
public BindingList<Message> AllMessagesBindingList
{
get { return _allMessagesBL; }
}
}
}

How can I redirect the stdout of IronPython in C#?

I have the following:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button3_Click(object sender, EventArgs e)
{
try
{
var strExpression = #"
import sys
sys.stdout=my.write
print 'ABC'
";
var engine = Python.CreateEngine();
var scope = engine.CreateScope();
var sourceCode = engine.CreateScriptSourceFromString(strExpression);
scope.SetVariable("my", this);
var actual = sourceCode.Execute<string>(scope);
textBox1.Text += actual;
}
catch (System.Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
public void write(string s)
{
textBox1.Text += s;
}
}
But I am getting an Exception that says there is no write.
What am I doing incorrectly?
You can set a stream and a textwriter directly from c#:
engine.Runtime.IO.SetOutput(stream, txtWriter);
engine.Runtime.IO.SetErrorOutput(stream, txtWriter);
To redirect the output for example you could override TextWriter class with a new one writing on your textbox.
e.g.
in my application I did an override of StreamWriter class that rises events when something is written on the stream (here just a part of the code):
public class MyEvtArgs<T> : EventArgs
{
public T Value
{
get;
private set;
}
public MyEvtArgs(T value)
{
this.Value = value;
}
}
public class EventRaisingStreamWriter : StreamWriter
{
#region Event
public event EventHandler<MyEvtArgs<string>> StringWritten;
#endregion
#region CTOR
public EventRaisingStreamWriter(Stream s):base(s)
{ }
#endregion
#region Private Methods
private void LaunchEvent(string txtWritten)
{
if (StringWritten != null)
{
StringWritten(this, new MyEvtArgs<string>(txtWritten));
}
}
#endregion
#region Overrides
public override void Write(string value)
{
base.Write(value);
LaunchEvent(value);
}
public override void Write(bool value)
{
base.Write(value);
LaunchEvent(value.ToString());
}
// here override all writing methods...
#endregion
}
Then in your application you should just do something like:
MemoryStream ms = new MemoryStream();
EventRaisingStreamWriter outputWr = new EventRaisingStreamWriter(ms);
outputWr.StringWritten += new EventHandler<MyEvtArgs<string>>(sWr_StringWritten);
var engine = Python.CreateEngine();
engine.Runtime.IO.SetOutput(ms, outputWr);
engine.CreateScriptSourceFromString("print 'hello world!'").Execute();
void sWr_StringWritten(object sender, MyEvtArgs<string> e)
{
textBox1.Text += e.Value;
}
Your example is close to working.
The problem you saw is because sys.stdout=my.write should be sys.stdout=my.
It also appears that Python expects to find a boolean softspace attribute.
I have made these two changes in the code below. Hopefully this should now work as you expected.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button3_Click(object sender, EventArgs e)
{
try
{
var strExpression = #"
import sys
sys.stdout=my
print 'ABC' ";
var engine = Python.CreateEngine();
var scope = engine.CreateScope();
var sourceCode = engine.CreateScriptSourceFromString(strExpression);
scope.SetVariable("my", this);
var actual = sourceCode.Execute(scope);
textBox1.Text += actual;
} catch (System.Exception ex) {
MessageBox.Show(ex.ToString());
}
}
public bool softspace;
public void write(string s)
{
textBox1.Text += s;
}
}
This worked fine for me
pyRuntime = Python.CreateRuntime();
pyRuntime.IO.SetOutput(Console.OpenStandardOutput(), new UTF8Encoding(true, false));

Categories