Extract a string from a webpage - c#

i need to have a label where its text comes from a web page, but for somting it doesnt work out, it appearce to me that the webpae returned null, but the location is correct.
WebBrowser JOJO = new WebBrowser();
string Tesla = "";
JOJO.Url = new Uri("https://finance.yahoo.com/quote/TSLA?p=TSLA");
var sal = JOJO.Document.GetElementsByTagName("div");// this return null
foreach (HtmlElement link in sal)
{
if (link.GetAttribute("className") == "D(ib) Mend(20px)")/*this is the class of the element*/
{
Tesla = link.FirstChild.InnerHtml;
}
}
label11.Text = Tesla;
this is the code that i have done so far, can someone see why dosnt work?
Thanks.

It is null because it didn't load yet when you try to access it. You should be handling it asynchronously.
Handle the DocumentCompleted event and access the Document in the handler.
Replace the code you have with:
WebBrowser JOJO = new WebBrowser();
JOJO.DocumentCompleted += new System.Windows.Forms.WebBrowserDocumentCompletedEventHandler
(this.BrowserDocumentCompleted);
JOJO.Url = new Uri("https://finance.yahoo.com/quote/TSLA?p=TSLA");
And here is the handler:
void BrowserDocumentCompleted(object sender,
WebBrowserDocumentCompletedEventArgs e)
{
if (e.Url.AbsolutePath != (sender as WebBrowser).Url.AbsolutePath)
return;
string Tesla = "";
var sal = (sender as WebBrowser).Document.GetElementsByTagName("div");
foreach (HtmlElement link in sal)
{
if (link.GetAttribute("className") == "D(ib) Mend(20px)")
{
Tesla = link.FirstChild.InnerHtml;
}
}
label1.Text = Tesla;
}
Now you will maybe face other problems with redirections. But that is another discussion :)

Related

Google Places Autocomplete does not populate the address

I have an active Google Places autocomplete working with Xamarin Forms or Cross Platform. I have a working solution that auto populates the address when the user types in the address. My problem is when the user selects it from the list the address does not go to the search_bar.text… The search bar just remains with the text that was typed? how can I get the text when selected to populate in the search bar.
I am new to Xamarin forms and C#.
public Createbusinessaccount ()
{
InitializeComponent ();
search_bar.ApiKey = GooglePlacesApiKey;
search_bar.Type = PlaceType.Address;
search_bar.Components = new Components("country:us"); // Restrict results to Australia and New Zealand
search_bar.PlacesRetrieved += Search_Bar_PlacesRetrieved;
search_bar.TextChanged += Search_Bar_TextChanged;
search_bar.MinimumSearchText = 2;
results_list.ItemSelected += Results_List_ItemSelected;
}
void Search_Bar_PlacesRetrieved(object sender, AutoCompleteResult result)
{
results_list.ItemsSource = result.AutoCompletePlaces;
spinner.IsRunning = false;
spinner.IsVisible = false;
if (result.AutoCompletePlaces != null && result.AutoCompletePlaces.Count > 0)
results_list.IsVisible = true;
}
void Search_Bar_TextChanged(object sender, TextChangedEventArgs e)
{
if (!string.IsNullOrEmpty(e.NewTextValue))
{
results_list.IsVisible = false;
spinner.IsVisible = true;
spinner.IsRunning = true;
}
else
{
results_list.IsVisible = true;
spinner.IsRunning = false;
spinner.IsVisible = false;
}
}
async void Results_List_ItemSelected(object sender, SelectedItemChangedEventArgs e)
{
if (e.SelectedItem == null)
return;
var prediction = (AutoCompletePrediction)e.SelectedItem;
results_list.SelectedItem = null;
var place = await Places.GetPlace(prediction.Place_ID, GooglePlacesApiKey);
if (place != null)
await DisplayAlert(
place.Name, string.Format("Lat: {0}\nLon: {1}", place.Latitude, place.Longitude), "OK");
}
In your ItemSelected method, you need to set the text of the searchbar:
async void Results_List_ItemSelected(object sender, SelectedItemChangedEventArgs e)
{
if (e.SelectedItem == null)
return;
var prediction = (AutoCompletePrediction)e.SelectedItem;
search_bar.Text = prediction.Name? // Your property here
results_list.SelectedItem = null;
var place = await Places.GetPlace(prediction.Place_ID, GooglePlacesApiKey);
if (place != null)
await DisplayAlert(
place.Name, string.Format("Lat: {0}\nLon: {1}", place.Latitude, place.Longitude), "OK");
}
I am still trying to fix this, it only adds the street name and number not the whole address

UWP C# Menuflyout Unable To Display Item Properly During 1st Click

I am having an issue with my code to add button from json where the first attempt i click add button, the menuflyout won't have any respond but second click attempt then it will work properly.
Can advise did i do anything wrong? Thanks.
private async void AddButton_Click(object sender, RoutedEventArgs e)
{
List<ClientList> clientLists;
var jsonSerializer = new DataContractJsonSerializer(typeof(List<ClientList>));
var myStream = await ApplicationData.Current.LocalFolder.OpenStreamForReadAsync(CLIENTSLIST);
clientLists = (List<ClientList>)jsonSerializer.ReadObject(myStream);
var menuFlyout = new MenuFlyout();
int isEmpty = myGrid.Children.Count;
if (isEmpty == 0)
{
foreach (var device in clientLists)
{
var menuFlyoutItem = new MenuFlyoutItem() { Name = device.clientname, Text = device.clientname };
menuFlyoutItem.Tag = device.clientaddress;
menuFlyoutItem.Click += AddMenuFlyoutItem_Click;
menuFlyout.Items.Add(menuFlyoutItem);
}
}else
{
foreach (var device in clientLists)
{
bool toAddButton = true;
foreach (Button btn in myGrid.Children.OfType<Button>())
{
if (btn.Content.ToString() == device.clientname)
{
toAddButton = false;
}
}
if (toAddButton)
{
var menuFlyoutItem = new MenuFlyoutItem() { Name = device.clientname, Text = device.clientname };
menuFlyoutItem.Tag = device.clientaddress;
menuFlyoutItem.Click += AddMenuFlyoutItem_Click;
menuFlyout.Items.Add(menuFlyoutItem);
}
}
}
AddButton.Flyout = menuFlyout;
}
The problem is you are loading the data asynchronously here:
var myStream = await ApplicationData.Current.LocalFolder.OpenStreamForReadAsync(CLIENTSLIST);
When this happens, UI continues executing the Click event, so the button is clicked (and Flyout is null the first time) and Flyout will never display. You should rather load the Flyout before that - either when the page loads or when the data source changes, so that when the user clicks, the flyout is already there. Doing loading in Click is simply too late, if you need an asynchronous operation to finish.
Alternatively you could set the flyout right at the start:
private async void AddButton_Click(object sender, RoutedEventArgs e)
{
var menuFlyout = new MenuFlyout();
AddButton.Flyout = menuFlyout;
List<ClientList> clientLists;
var jsonSerializer = new DataContractJsonSerializer(typeof(List<ClientList>));
var myStream = await ApplicationData.Current.LocalFolder.OpenStreamForReadAsync(CLIENTSLIST);
clientLists = (List<ClientList>)jsonSerializer.ReadObject(myStream);
int isEmpty = myGrid.Children.Count;
if (isEmpty == 0)
{
foreach (var device in clientLists)
{
var menuFlyoutItem = new MenuFlyoutItem() { Name = device.clientname, Text = device.clientname };
menuFlyoutItem.Tag = device.clientaddress;
menuFlyoutItem.Click += AddMenuFlyoutItem_Click;
menuFlyout.Items.Add(menuFlyoutItem);
}
}else
{
foreach (var device in clientLists)
{
bool toAddButton = true;
foreach (Button btn in myGrid.Children.OfType<Button>())
{
if (btn.Content.ToString() == device.clientname)
{
toAddButton = false;
}
}
if (toAddButton)
{
var menuFlyoutItem = new MenuFlyoutItem() { Name = device.clientname, Text = device.clientname };
menuFlyoutItem.Tag = device.clientaddress;
menuFlyoutItem.Click += AddMenuFlyoutItem_Click;
menuFlyout.Items.Add(menuFlyoutItem);
}
}
}
}
This way, the flyout will appear, but will be empty until the asynchronous loading finishes and the items are actually added. Here you are just reading a file, so it should be barely noticeable. Although not as clean as pre-loading the flyout, it should get the job done too.

Find PlaceHolder another PlaceHolder

I've strange problem... :/
I have on my page PlaceHolder, where I generate dynamically more PlaceHolders.
I've stored names of this dynamicaly created PlaceHolders.
When I try to find any of this PlaceHolders - I've got error null reference to an Object.
Please help! :)
private void btnMoreInfo_Click(object sender, EventArgs e)
{
Button button = sender as Button;
string[] componentName = button.ID.Split('_');
String controlName = null;
foreach (String singlePlaceHolder in placeHolderNames)
{
if (singlePlaceHolder.Contains(componentName[0]))
controlName = singlePlaceHolder;
}
Control cph = this.Master.FindControl(controlName);
Label helperlabel = new Label();
helperlabel.Text = "That one!";
cph.Controls.Add(helperlabel);
cph.Visible = true;
}
I changed code to this, and it's working now:
var cph = FindControlRecursive(this.Master, controlName);
plus I added new method:
private Control FindControlRecursive(Control root, string id)
{
if(root.Id==id)
{
return root;
}
foreach (Control c in root.Controls)
{
Control t= FindControlRecursaive(c, id);
if (t !=null)
{
return t;
}
}
return null;
}

collapse all elements for loaded xml in webbrowser control using c#

I am using the System.Windows.Forms.WebBrowser to display XML in a syntax highlighted and easy to traverse format. Whenever I load the XML into the Control, I would like to have all the elements collapsed, is this possible?
This is triggered by the DocumentCompleted event handler.
this was a useful link to help with java script injection:
How to execute custom JavaScript in WebBrowser control?
I used the following code.
private void CollapseExpandDocument(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if (sender == null)
{
return;
}
try
{
WebBrowser me = (WebBrowser) sender;
HtmlElement head = me.Document.GetElementsByTagName("head")[0];
HtmlElement scriptEl = me.Document.CreateElement("script");
IHTMLScriptElement element = (IHTMLScriptElement)scriptEl.DomElement;
string func = #"
function collapseDoc()
{
var className = 'b';
var hasClassName = new RegExp('(?:^|\\s)' + className + '(?:$|\\s)');
var allElements = document.getElementsByTagName('a');
var element;
for (var i = 0; (element = allElements[i]) != null; i++)
{
var elementClass = element.className;
if (elementClass && elementClass.indexOf(className) != -1 && hasClassName.test(elementClass))
ch(element.parentElement.parentElement);
}
}";
element.text = func;
head.AppendChild(scriptEl);
me.Document.InvokeScript("collapseDoc");
}
catch
{
//not interested in knowing if the collapse/expand failed...
}
}

My code causes URL to open in 2 different tabs, why?

As person helped me to figure out how to start open URL in default browser now I am having bit of a problem which causes to open URL in 2 different tabs when clicked. What could be the cause for this?
EDIT: I think it's good to point out that I am using a ListView in detailed mode. So when user clicks column with URL, it should open a single window in the browser.
lvWeb.MouseMove += new MouseEventHandler(lvWeb_MouseMove);
lvWeb.MouseUp +=new MouseEventHandler(lvWeb_MouseUp);
private void lvWeb_MouseMove(object sender, MouseEventArgs e)
{
var hit = lvWeb.HitTest(e.Location);
if (hit.SubItem != null && hit.SubItem == hit.Item.SubItems[1])
lvWeb.Cursor = Cursors.Hand;
else lvWeb.Cursor = Cursors.Default;
}
private void lvWeb_MouseUp(object sender, MouseEventArgs e)
{
var hit = lvWeb.HitTest(e.Location);
if (hit.SubItem != null && hit.SubItem == hit.Item.SubItems[1])
{
var url = new Uri(hit.SubItem.Text);
System.Diagnostics.Process.Start(url.ToString());
}
}
As one person sugested, I have visited the article which did the trick and it works as following:
private string getDefaultBrowser()
{
string browser = string.Empty;
RegistryKey key = null;
try
{
key = Registry.ClassesRoot.OpenSubKey(#"HTTP\shell\open\command", false);
//trim off quotes
browser = key.GetValue(null).ToString().ToLower().Replace("\"", "");
if (!browser.EndsWith("exe"))
{
//get rid of everything after the ".exe"
browser = browser.Substring(0, browser.LastIndexOf(".exe") + 4);
}
}
finally
{
if (key != null) key.Close();
}
return browser;
}
private void lvWeb_MouseUp(object sender, MouseEventArgs e)
{
var hit = lvWeb.HitTest(e.Location);
if (hit.SubItem != null && hit.SubItem == hit.Item.SubItems[1])
{
var url = new Uri(hit.SubItem.Text);
//System.Diagnostics.Process.Start(url.ToString());
Process p = new Process();
p.StartInfo.FileName = getDefaultBrowser();
p.StartInfo.Arguments = url.ToString();
p.Start();
}
}

Categories