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; }
}
}
Related
I'm working on Xamarin forms project and i have implemented Interstitial ad on all three platforms (Google admob doesn't support UWP). Ads are working fine but they are showing with a delay of 4 to 5 seconds. All i want is to finish that delay so they can show immediately.
PCL class.
public interface IAdmobInterstitial
{
void Show(string adUnit);
}
Droid Code.
public class InterstitialAdListener : AdListener
{
readonly InterstitialAd _ad;
public InterstitialAdListener(InterstitialAd ad)
{
_ad = ad;
}
public override void OnAdLoaded()
{
base.OnAdLoaded();
if (_ad.IsLoaded)
_ad.Show();
}
}
public class AdmobInterstitial : Controls.IAdmobInterstitial
{
InterstitialAd _ad;
public void Show(string adUnit)
{
var context = Android.App.Application.Context;
_ad = new InterstitialAd(context);
_ad.AdUnitId = adUnit;
var intlistener = new InterstitialAdListener(_ad);
intlistener.OnAdLoaded();
_ad.AdListener = intlistener;
var requestbuilder = new AdRequest.Builder().AddTestDevice("302E90D530B2193F59FDD7F22A11B45A");
_ad.LoadAd(requestbuilder.Build());
}
}
iOS Code.
public class AdmobInterstitial : IAdmobInterstitial
{
Interstitial _adInterstitial;
public void Show(string adUnit)
{
_adInterstitial = new Interstitial(adUnit);
var request = Request.GetDefaultRequest();
_adInterstitial.AdReceived += (sender, args) =>
{
if (_adInterstitial.IsReady)
{
var window = UIApplication.SharedApplication.KeyWindow;
var vc = window.RootViewController;
while (vc.PresentedViewController != null)
{
vc = vc.PresentedViewController;
}
_adInterstitial.PresentFromRootViewController(vc);
}
};
_adInterstitial.LoadRequest(request);
}
}
Calling interstitial ad on PCL page.
DependencyService.Get<IAdmobInterstitial>().Show("(id will come here)");
Navigation.PushAsync(new Page());
Ad is showing perfectly but with a delay. I want to show the ad first and then the page.
So i just solved this.
Here is the code.
PCL Class. Add another function to your interface.
public interface IAdmobInterstitial
{
void Show(string adUnit);
void Give();
}
Droid code. Put _ad.Show() in the new function.
public class InterstitialAdListener : AdListener
{
readonly InterstitialAd _ad;
public InterstitialAdListener(InterstitialAd ad)
{
_ad = ad;
}
public override void OnAdLoaded()
{
base.OnAdLoaded();
//if (_ad.IsLoaded)
// _ad.Show();
}
}
public class AdmobInterstitial : Controls.IAdmobInterstitial
{
InterstitialAd _ad;
public void Show(string adUnit)
{
var context = Android.App.Application.Context;
_ad = new InterstitialAd(context);
_ad.AdUnitId = adUnit;
var intlistener = new InterstitialAdListener(_ad);
intlistener.OnAdLoaded();
_ad.AdListener = intlistener;
var requestbuilder = new AdRequest.Builder().AddTestDevice("302E90D530B2193F59FDD7F22A11B45A");
_ad.LoadAd(requestbuilder.Build());
}
public void Give()
{
if (_ad.IsLoaded)
_ad.Show();
}
}
Now, call the function Show() in the constructor of your MainPage in PCL and call the function Give() when you press the button for the next page.
public MainPage()
{
InitializeComponent();
DependencyService.Get<IAdmobInterstitial>().Show("ca-app-pub-3940256099942544/1033173712");
}
private void button_Clicked(object sender, EventArgs e)
{
DependencyService.Get<IAdmobInterstitial>().Give();
Navigation.PushAsync(new Percentage());
}
This is only for Android. Same goes for iOS as well.
I hope it helps the other programmers. :)
I am handling an event from a child form in its parent form, and when I try adding items from the list contained within the event args of the handler (ScraperForm_SiteScraped in the code below), I am receiving the exception System.InvalidOperationException in my console.
Interestingly enough, it seems to succeed on the first add, but no subsequent attempts.
public partial class ProxyTesterView : UserControl
{
private BindingList<Proxy> proxies = new BindingList<Proxy>();
private BindingList<ProxyJudge> pudges = new BindingList<ProxyJudge>();
private BindingList<ProxyTest> tests = new BindingList<ProxyTest>();
private PauseOrCancelTokenSource pcts = new PauseOrCancelTokenSource();
private ProxyScraperForm scraperForm = new ProxyScraperForm();
public ProxyTesterView()
{
InitializeComponent();
proxies.ListChanged += Proxies_ListChanged;
scraperForm.SiteScraped += ScraperForm_SiteScraped;
}
private void Proxies_ListChanged(object sender, ListChangedEventArgs e)
{
ProxiesDataGridView.RowCount = proxies.Count;
}
private void AddFromScraperToolStripMenuItem_Click(object sender, EventArgs e)
{
scraperForm.Show();
}
private void ScraperForm_SiteScraped(object sender, SiteScrapedEventArgs e)
{
foreach (var proxy in e.ScrapedProxies)
{
proxies.Add(proxy);
}
}
}
Child Form
public partial class ProxyScraperForm : Form
{
private BindingList<IProxyScraperSite> sites = new BindingList<IProxyScraperSite>();
public int ScrapeInterval { get; set; } = 60000;
public event EventHandler<SiteScrapedEventArgs> SiteScraped;
public ProxyScraperForm()
{
InitializeComponent();
sites.Add(new ProxyScraperSiteUsProxyOrg());
sites.Add(new ProxyScraperSiteFreeProxyListNet());
sites.Add(new ProxyScraperSiteFreeProxyListsNet());
sites.Add(new ProxyScraperSiteHideMyName());
sites.Add(new ProxyScraperSiteHidester());
ScraperDataGridView.DataSource = sites;
}
private void ScrapeButton_Click(object sender, EventArgs e)
{
foreach (var site in sites)
{
Task.Run(async () =>
{
while (true)
{
var driver = SeleniumUtility.CreateDefaultFirefoxDriver();
var newProxies = await site.ScrapeAsync(driver);
driver.Quit();
OnSiteScraped(newProxies);
await Task.Delay(5000);
site.Status = $"Waiting {ScrapeInterval / 1000} seconds...";
await Task.Delay(ScrapeInterval);
}
});
}
}
private void OnSiteScraped(List<Proxy> scrapedProxies)
{
if (SiteScraped != null)
{
SiteScraped(this, new SiteScrapedEventArgs(scrapedProxies));
}
}
}
From our comments, turns out that this was a threading issue. As a good practice, always use a try/catch block when there's a chance that an exception can occur in a block of code. :)
Also, if you're using Visual Studio, you can make VS break on more exceptions by pressing CTRL+ALT+E and selecting the checkboxes. You can read more about exception breaking here.
I have a M2MQTT client subscribed to a topic in the DashboardViewModel class. On message receive, the UI gets updated by calling Writelog.
public class DashboardViewModel : Object, IDashboardViewModel
{
private IDashboardView View { get; }
public DashboardViewModel(IDashboardView view)
{
View = view;
mqttClient = new MqttClient("localhost");
mqttClientId = Guid.NewGuid().ToString();
mqttClient.MqttMsgPublishReceived += mqttClient_MsgPublishReceived;
mqttClient.Subscribe(new string[] { "Home/Temperature" }, new byte[] { MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE });
mqttClient.Connect(mqttClientId);
//...
}
private void mqttClient_MsgPublishReceived(object sender, MqttMsgPublishEventArgs eventArgs)
{
string message = Encoding.UTF8.GetString(eventArgs.Message);
View.Writelog(message);
}
}
The textbox on FrmMain does not update; tbxLogs.InvokeRequired always returns false, i.e. tbxLogs.AppendText always executes. Any suggestions please?
public partial class FrmMain : Form, IDashboardView
{
private IDashboardViewModel dashboardViewModel = null;
private delegate void WriteLogCallback(string text);
public FrmMain()
{
InitializeComponent();
}
public void Writelog(string text)
{
if (tbxLogs.InvokeRequired)
{
WriteLogCallback callback = new WriteLogCallback(Writelog);
tbxLogs.Invoke(callback, new object[] { text });
}
else
{
tbxLogs.AppendText(text + "\n");
}
}
}
I think you need to use dispatcher :)
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action<String>(Writelog), message);
inside of this method
private void mqttClient_MsgPublishReceived(object sender, MqttMsgPublishEventArgs eventArgs)
{
string message = Encoding.UTF8.GetString(eventArgs.Message);
//here instead of View.Writelog(message);
}
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.
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; }
}
}
}