How to grab webbrowser.document using caliburn.micro WPF - c#

I have a web browser in WPF
<WebBrowser x:Name="WebBrowserControl" Width="1000" Height="600" Source="https://www.1.com" cal:Message.Attach="[Event LoadCompleted]=[Action LoadCompleted($eventArgs)]"/>
It loads the www.1.com and when i click a button on 1.com it jump to http://2.com
I listen to loadCompleted event
public void LoadCompleted(NavigationEventArgs e)
{
if (e.Uri.AbsoluteUri == "https://www.2.com")
{
//Here i want to get WebBrowserControl.Document as mshtml.HTMLDocument;
MessageBox.Show("Completed loading the page");
}
}
I want to get 2.com htmlDocument. is there a way to achieve that. I achieve that in not viewmodel way.
private void WebBrowserControl_LoadCompleted(object sender, NavigationEventArgs e)
{
string[] tags = new string[]{};
if (e.Uri.OriginalString == "https://www.2.com")
{
MessageBox.Show("here");
var document = WebBrowserControl.Document as mshtml.HTMLDocument;
}
}
I did something like this
//view
cal:Message.Attach="[Event LoadCompleted]=[Action LoadCompleted(WebBrowserControl.Document,$eventArgs)]"
//ViewModel
public void LoadCompleted(mshtml.HTMLDocument x ,NavigationEventArgs e)
{
//it calls this method but the x is null
}

<WebBrowser x:Name="WebBrowserControl" Width="1000" Height="600" Source="https://www.1.com" cal:Message.Attach="[Event LoadCompleted]=[Action LoadCompleted($source,$eventArgs)]"/>
public void LoadCompleted(object sender ,NavigationEventArgs e)
{
WebBrowser x = (WebBrowser)sender;
var document = x.Document as mshtml.HTMLDocument;
}

Related

Bug in PopupMenu when background work is begin done?

I am building a Universal App and I think I have found a bug in the Windows Phone 8.1 PopupMenu control. I have been able to reproduce it with a small piece of code. It works fine on Windows 8 but not on Windows Phone 8.1.
Whenever I create a PopupMenu from within a button click it doesn't return from ShowFromSelectionAsync() when there is a background task running ? Why ?
The same code works on Windows 8.
I my application a lot of background work is being done, so the control doesn't work correctly on Phone anymore. Any suggestions how to fix this ?
I have a MainPage.xaml:
<Page
x:Class="PopupMenuBugPhone.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:PopupMenuBugPhone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<StackPanel>
<Button Content="Test Bug" Click="Button_Click" />
</StackPanel>
</Grid>
</Page>
MainPage.xaml.cs:
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
var frameworkElement = sender as FrameworkElement;
var task = SimulateBackgroundWork(); // COMMENT THIS TO MAKE IT WORK ON PHONE!!!
var menu = new PopupMenu();
var сmdOption1 = new UICommand("Option1");
var cmdOption2 = new UICommand("Option2");
menu.Commands.Add(сmdOption1);
menu.Commands.Add(cmdOption2);
// We don't want to obscure content, so pass in a rectangle representing the sender of the context menu event.
var chosenCommand = await menu.ShowForSelectionAsync(frameworkElement.GetElementRect());
if (chosenCommand == null) // The command is null if no command was invoked.
{
await new MessageDialog("No choice").ShowAsync();
}
else
{
await new MessageDialog("Choice: " + chosenCommand.Label).ShowAsync();
}
await task; // COMMENT THIS TO MAKE IT WORK ON PHONE!!!
}
private Task SimulateBackgroundWork()
{
var t = Task.Run(() =>
{
var dt = DateTime.Now;
// Do some dummy processing loop
while (DateTime.Now < dt.AddSeconds(300))
{
;
}
});
return t;
}
}
How about using a MenuFlyout?
Let's say you defined it in code-behind of the page, along with the TaskCompletionSource to wrap it to make showing awaitable:
MenuFlyout flyout = new MenuFlyout();
TaskCompletionSource<string> tcs;
Then on button click you could do this:
private async void Button_Click(object sender, RoutedEventArgs e)
{
var frameworkElement = sender as FrameworkElement;
var task = SimulateBackgroundWork();
flyout.Closed += flyout_Closed;
var mf1 = new MenuFlyoutItem { Text = "Option1" };
var mf2 = new MenuFlyoutItem { Text = "Option2" };
mf1.Click += mf_Click;
mf2.Click += mf_Click;
flyout.Items.Clear();
flyout.Items.Add(mf1);
flyout.Items.Add(mf2);
await ShowMenuFlyout(sender as FrameworkElement);
await task;
}
ShowMenuFlyout is awaitable and implemented like this:
public Task<string> ShowMenuFlyout(FrameworkElement sender)
{
tcs = new TaskCompletionSource<string>();
flyout.ShowAt(sender as FrameworkElement);
return tcs.Task;
}
And event handlers would simply do this:
async void mf_Click(object sender, RoutedEventArgs e)
{
flyout.Closed -= flyout_Closed;
await new MessageDialog("Choice: " + (sender as MenuFlyoutItem).Text).ShowAsync();
tcs.SetResult((sender as MenuFlyoutItem).Text);
}
async void flyout_Closed(object sender, object e)
{
flyout.Closed -= flyout_Closed;
await new MessageDialog("No choice").ShowAsync();
tcs.SetResult("No choice");
}
This works on both platforms. Of course, this is just proof of concept, you might want a null check here or there, but it works.

Change image of a button that is on an element of a LongListSelector

I have this longListSelector:
<phone:LongListSelector
x:Name="ListaMensajesTablon"
ItemsSource="{Binding Mensajes}"
ItemTemplate="{StaticResource MensajesTablonDataTemplate}"
SelectionChanged="MensajeTablonSelected"/>
With this ItemTemplate:
<DataTemplate x:Key="MensajesTablonDataTemplate">
<Grid>
<Button MaxHeight="85" MaxWidth="95" MinHeight="85" MinWidth="95" Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Center" Click="Button_Click" BorderBrush="Transparent">
<Button.Content>
<Image x:Name="imagenFav" MaxHeight="75" MaxWidth="75" MinHeight="75" MinWidth="75"
Source="{Binding userFav, Converter={StaticResource BoolToHeart}}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Button.Content>
</Button>
</Grid>
</DataTemplate>
This code-behind:
private void Button_Click(object sender, RoutedEventArgs e)
{
botonFavPulsado = true;
botonAmor = (Button)sender;
}
private void MensajeTablonSelected(object sender, SelectionChangedEventArgs e)
{
if(botonFavPulsado)
{
var myItem = ((LongListSelector)sender).SelectedItem as MensajeTablon;
if(botonAmor!=null)
{
if (myItem.userFav)
{
botonAmor.Content = new Image
{
Source = new BitmapImage(new Uri("icons/heart.red.png", UriKind.Relative))
};
}
else
{
botonAmor.Content = new Image
{
Source = new BitmapImage(new Uri("icons/heart.white.png", UriKind.Relative))
};
}
}
botonFavPulsado = false;
}
}
I want to do is that when you press a button that is inside an element of LongListSelector change the picture . The first time I press the button enters in the function Button_Click and then enters in the function MensajeTablonSelected function and change the image (good). The problem is the second time I press the same button is entering in the function Button_Click function and does not enter in the function MensajeTablonSelected
Resume : ToggleButton in LongItemSelector working the first time but not the second one
Problem solved:
private void MensajeTablonSelected(object sender, SelectionChangedEventArgs e)
{
if (((LongListSelector)sender).SelectedItem != null)
if(botonFavPulsado)
{
var myItem = ((LongListSelector)sender).SelectedItem as MensajeTablon;
if(botonAmor!=null)
{
if (myItem.userFav)
{
botonAmor.Content = new Image
{
Source = new BitmapImage(new Uri("icons/heart.red.png", UriKind.Relative))
};
}
else
{
botonAmor.Content = new Image
{
Source = new BitmapImage(new Uri("icons/heart.white.png", UriKind.Relative))
};
}
}
botonFavPulsado = false;
//Unselect ITEM
((LongListSelector)sender).SelectedItem = null;
}
}
This solution have a problem, the function MensajeTablonSelected is called again.

How to programatically modify web browser content in design mode?

here's my dependency property declared :
public static void IsDesignModePropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
{
WebBrowser browser = obj as WebBrowser;
if (browser != null)
{
Boolean designMode = (Boolean)args.NewValue;
if (designMode)
{
browser.LoadCompleted += (s, e) =>
{
var htmlDoc = (s as WebBrowser).Document as IHTMLDocument2;
htmlDoc.body.setAttribute("contenteditable", "true");
htmlDoc.designMode = "On";
};
}
else
{
browser.LoadCompleted += (s, e) =>
{
var htmlDoc = (s as WebBrowser).Document as IHTMLDocument2;
htmlDoc.body.setAttribute("contenteditable", "false");
htmlDoc.designMode = "Off";
};
}
}
}
here's my web browser control :
<WebBrowser viewmodel:BrowserBehavior.IsDesignMode="True" x:Name="webBrowser1" viewmodel:BrowserBehavior.Html="{Binding SelectedNode.ContentData.FileName, Converter={StaticResource converter}, Mode=OneWay}" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Width="612"/>
i would like to programatically modify the content of the web browser , and disable modification by keyboard ; i mean with a button that act on selection !
How is that possible ?
i found how to disable keyboard while IsDesignMode ="true" :
<WebBrowser KeyDown="webBrowser1_KeyDown" ... />
in code behind :
private void webBrowser1_KeyDown(object sender, KeyEventArgs e)
{
e.Handled = true;
}
Still looking for the answer of the second part of my question !

Windows Phone Refresh button not working

I have a Windows phone application which gets a list of photos URLs from a SQL database depending what it uploaded.
The issue i have is users can add their own photos to that list but it does not refresh the list on the page so i added a refresh to re run the code but it still does not run.
Well the code runs but does not update the list box.
//get/clean these strings
int parkID = 0;
string parkName = string.Empty;
public photos()
{
InitializeComponent();
BuildLocalizedApplicationBar();
}
private void ThemeParkPhotos_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error == null)
{
try
{
//No errors have been passed now need to take this file and parse it
//Its in XML format
XDocument xdox = XDocument.Parse(e.Result);
//need a list for them to be put in to
List<Photos> themeparkPhoto = new List<Photos>();
themeparkPhoto.Clear();
XNamespace ns = "http://schemas.datacontract.org/2004/07/WCFServiceWebRole1";
//Now need to get every element and add it to the list
foreach (XElement item in xdox.Descendants(ns + "Photos"))
{
Photos content = new Photos();
content.ID = Convert.ToInt32(item.Element(ns + "ID").Value);
content.PhotoURL = Convert.ToString(item.Element(ns + "PhotoURL").Value);
//content.ID = Convert.ToInt32(item.Element(ns + "id").Value);
//content.ThemeParkName = item.Element(ns + "name").Value.ToString();
themeparkPhoto.Add(content);
}
ThemeParkPhoto.ItemsSource = null;
ThemeParkPhoto.ItemsSource = themeparkPhoto.ToList();
//Delete all the stuff
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
else
{
//There an Error
}
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
//This is to get the data that was passed from the home screen to which song to use!
base.OnNavigatedTo(e);
if ((NavigationContext.QueryString["pID"] == string.Empty) || (NavigationContext.QueryString["pName"] == string.Empty))
{
//if not show message box.
MessageBox.Show("Empty Vaules have been sent, Please got back and try again");
}
else
{
parkID = Convert.ToInt32(NavigationContext.QueryString["pID"]);
parkName = NavigationContext.QueryString["pName"].ToString();
PageName.Text = parkName;
GetThemeParkPhotos();
}
}
public void GetThemeParkPhotos()
{
WebClient ThemeParkPhotos = new WebClient();
ThemeParkPhotos.DownloadStringCompleted += ThemeParkPhotos_DownloadStringCompleted;
ThemeParkPhotos.DownloadStringAsync(new Uri("HIDDEDURL/viewphotos?format=xml&themeparkid=" + parkID));
//MessageBox.Show("Test if this works"+parkID);
}
private void BuildLocalizedApplicationBar()
{
ApplicationBar = new ApplicationBar();
ApplicationBar.Mode = ApplicationBarMode.Default;
ApplicationBar.Opacity = 1.0;
ApplicationBar.IsVisible = true;
ApplicationBar.IsMenuEnabled = true;
ApplicationBarIconButton AddButton = new ApplicationBarIconButton();
AddButton.IconUri = new Uri("/Images/add.png", UriKind.Relative);
AddButton.Text = "Add Photo";
ApplicationBar.Buttons.Add(AddButton);
AddButton.Click +=AddButton_Click;
//Dont add refresh button as it does not work at this time :(
ApplicationBarIconButton RefreshButton = new ApplicationBarIconButton();
RefreshButton.IconUri = new Uri("/Images/refresh.png", UriKind.Relative);
RefreshButton.Text = "Refresh";
ApplicationBar.Buttons.Add(RefreshButton);
RefreshButton.Click += RefreshButton_Click;
}
private void RefreshButton_Click(object sender, EventArgs e)
{
GetThemeParkPhotos();
}
private void AddButton_Click(object sender, EventArgs e)
{
//need to send them to add a photo page with details.
NavigationService.Navigate(new Uri("/TakePhoto.xaml?pID=" + parkID + "&pName=" + parkName, UriKind.Relative));
}
Here the Code for the ListBox
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<ListBox Height="559" HorizontalAlignment="Left" Margin="6,20,0,0" x:Name="ThemeParkPhoto" VerticalAlignment="Top" Width="444" FontSize="30" ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock x:Name="ID" Text="{Binding ID}"></TextBlock>
<Image x:Name="PhotoURL" Source="{Binding PhotoURL}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
I have removed the URL to save the API, That code does run and fill it but why does it not refresh the List Box correctly?
Many Thanks
Thank to being sent here : C# WebClient disable cache
Turns out that Windows phone web client caches the file meaning it never download it again until the app is refreshed. By using a random number generator and adding it to the then of the URL it will always download the file allowing for a refresh.

How to use WebBrowser in windows phone?

I'm using the following code to make my app to load a url,
WebBrowser wb = new WebBrowser();
wb.Navigate(new Uri(uri,UriKind.Absolute));
But still it is not loading that page? What could be the problem??
WebBrowser is a control. Like a button or a textblock, you won't see anything unless you put it somewhere in your page.
To launch an external browser, use WebBrowserTask:
var webBrowserTask = new WebBrowserTask();
webBrowserTask.Uri = new Uri(uri, UriKind.Absolute);
webBrowserTask.Show();
Yo can't have any callbacks with the default WebBrowserTask in wp, if you need more control, use the WebBrowser as you have been doing,
Xaml
<phone:WebBrowser IsScriptEnabled="True" LoadCompleted="UriContentLoaded" x:Name="browserControl" />
Code Behind
public MainPage() //Your page constructor
{
InitializeComponent();
this.browserControl.Loaded += SetBrowserUri;
}
private void SetBrowserUri(object sender, RoutedEventArgs e)
{
browserControl.Navigate(new Uri("http://www.bing.com"));
}
private void UriContentLoaded(object sender, NavigationEventArgs e)
{
if (MessageBox.Show("Do you want to load a second uri?", "Load again", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
{
browserControl.LoadCompleted -= this.UriContentLoaded; //Remove previous handler
browserControl.LoadCompleted += this.SecondUriContentLoaded; //Add new handler
browserControl.Navigate(new Uri("http://www.google.com"));
}
}
private void SecondUriContentLoaded(object sender, NavigationEventArgs e)
{
MessageBox.Show("Finished loading");
}

Categories