How to access textBlock from another xaml window?
I have the Main Page and there is the event handler xmppClient_OnMessage. I want to do something like this:
void xmppClient_OnMessage(object sender, MessageEventArgs e)
{
this.NavigationService.Navigate(new Uri("/message.xaml", UriKind.Relative));
message.textBlock1.Text += e.Message.From + ": " + e.Message.Body;
}
you can pass the data using query parameters just like in html.
this.NavigationService.Navigate(new Uri("/message.xaml?messageid=1", UriKind.Relative));
and retrive it like this on next page
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
if (this.NavigationContext.QueryString.ContainsKey("messageid"))
{
//your code here
}
base.OnNavigatedTo(e);
}
You don't - by the time you navigate to another window the previous one will probably be gone (aka removed from memory). You should pass all the data you need via Navigation as query parameters or just have a static object in memory.
Related
I am trying to create a software in WPF which hosts a browser (WebView2 currently 1.0.818.41) and also show a OnScreenKeyboard when there is a input field focused in the browser.
I have done this kind of stuff with CefSharp in WPF before but I cannot do it with WebView2 currently. My problem is I do not find a way to send keystrokes from the OnScreenKeyboard (or from the WPF Window) to the Browser.
In CefSharp there we have a function called ChromiumWebBrowser.GetHost().SendKeyEvent() but I cannot find something similar in WebView2.
Am I blind or is this something which is currently not implemented (or maybe not planed)?
Thank you in advance!
There is no direct way. What can be done is execute some JS, which in turn posts a message to WebView. This message can then be caught back in wv2_WebMessageReceived event.
There is extensive documentation on the interop between.NET and JS and interop between JS and .NET WPF Forms here.
A solution would be to inject a sendMessage JS function in the NavigationStarting event:
private void wv2_NavigationStarting(Microsoft.UI.Xaml.Controls.WebView2 sender, Microsoft.Web.WebView2.Core.CoreWebView2NavigationStartingEventArgs args){
var sc = "function sendMessage(txt) { window.chrome.webview.postMessage(txt); }";
wv2.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync(sc);
}
Now you collect input fields and add onfocus and onblur events to these input fields for example in the NavigationCompleted event like this:
private void wv2_NavigationCompleted(Microsoft.UI.Xaml.Controls.WebView2 sender, Microsoft.Web.WebView2.Core.CoreWebView2NavigationCompletedEventArgs args){
string script = "const collection ="+
"document.getElementsByTagName(\"input\");" +
"for (let i = 0; i < collection.length; i++){" +
"collection[i].onfocus= ()=>{ sendMessage('onFocus('+collection[i].name')'); }; " +
"collection[i].onblur= (ev)=>{ sendMessage('onBlur('+collection[i].name')'); };"+
"}";
sender.ExecuteScriptAsync(script);
}
Now catch the message in the wv2_WebMessageReceived event:
private void wv2_WebMessageReceived(Microsoft.UI.Xaml.Controls.WebView2 sender, Microsoft.Web.WebView2.Core.CoreWebView2WebMessageReceivedEventArgs args)
{
var postMess = args.TryGetWebMessageAsString();
if (postMess == "onFocus(nameOfField)" )
{
// here activate the button(keyboard)
// store the Name on focusField variable
}
if (postMess == "onBlur" && paneShown)
{
// here deactivate the button(keyboard)
// release the focusField
}
}
Now you can send a click event to the input fields:
private void btn_Clicked(Object sender, EventArgs args)
{
var script = "var field "+
"= document.getElementsByName("+focusField+");" +
" field.value+=field.value"+args.keyValue();
wv2.CoreWebView2.ExecuteScriptAsync(script);
}
wv2 is an instance of WebView2 and the code is typed directly here and not compiled. Hope you get the idea.
I make a Wpf projcect which demos how to use WebView to Navigate a html file inside of the App, but fails.
The main cs file code is below:
public MainWindow()
{
this.InitializeComponent();
this.wv.ScriptNotify += Wv_ScriptNotify;
this.Loaded += MainPage_Loaded;
}
private async void Wv_ScriptNotify(object sender, Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT.WebViewControlScriptNotifyEventArgs e)
{
//await (new MessageDialog(e.Value)).ShowAsync();
textBlock.Text = e.Value;
//返回结果给html页面
await this.wv.InvokeScriptAsync("recieve", new[] { "hehe, 我是个结果" });
}
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
//我们事先写好了一个本地html页面用来做测试
this.wv.Source = new Uri("ms-appx-web://Assets/index.html");
//this.wv.Source = new Uri("http://www.baidu.com");
}
And the html file index.html is inside of the project, located at Assets/index.html. Its source code is here:
https://github.com/tomxue/WebViewIssueInWpf/raw/master/WpfApp3/Assets/index.html
I put the project code onto GitHub: https://github.com/tomxue/WebViewIssueInWpf.git
If the project works well, when WebView visits the inner html file, it should show a button at first.
But I saw nothing.
More:
According to the accepted answer(Thank to Pavel Anikhouski), I changed my code as below and it now works.
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
//我们事先写好了一个本地html页面用来做测试
//this.wv.Source = new Uri("ms-appx-web://Assets/index.html");
//this.wv.Source = new Uri("http://www.baidu.com");
var html = File.ReadAllText("../../Assets\\index.html");
wv.NavigateToString(html);
}
It seems to be a known issue with WebView control in WindowsCommunityToolkit
You can use only absolute URIs to resources in members of the WebView control that accept string paths.
WebView controls don't recognize the ms-appx:/// prefix, so they can't read from the package (if you've created a package for your
application).
WebView controls don't recognize the File:// prefix. If you want to read a file into a WebView control, add code to your application that
reads the content of the file. Then, serialize that content into a
string, and call the NavigateToString(String) method of the WebView
control.
So, instead of loading a file this.wv.Source = new Uri("ms-appx-web://Assets/index.html"); try to read a local file and then navigate to the string
var html = File.ReadAllText("Assets\\index.html");
this.wv.NavigateToString(html);
It should work fine (I've seen the button and message at my end). Also, don't forget to copy Assets\index.html to the output directory (set Copy Always or Copy if newer)
Hello
I have a problem in my Design which is in this http://archive.msdn.microsoft.com/wfxbap/Release/ProjectReleases.aspx?ReleaseId=4668
I have made a custom activity in my Re-hosted workflow designer in WPF, and I make this custom activity shows in the end-user toolbar with the other activites, but the custom one can't be drop into the sequence at all like other activities.
I put the AllowDrop="True" in the .XAML file and the following in the .cs file:
protected override void OnDragEnter(DragEventArgs e)
{
//Check the object is actually something we want to be droppable
if (DragDropHelper.AllowDrop(
e.Data,
this.Context,
typeof(Activity)))
{
e.Effects = (DragDropEffects.Move & e.AllowedEffects);
e.Handled = true;
}
base.OnDragEnter(e);
}
protected override void OnDragOver(DragEventArgs e)
{
//Check the object is actually something we want to be droppable
if (DragDropHelper.AllowDrop(
e.Data,
this.Context,
typeof(Activity)))
{
e.Effects = (DragDropEffects.Move & e.AllowedEffects);
e.Handled = true;
}
base.OnDragOver(e);
}
protected override void OnDrop(DragEventArgs e)
{
//droppedItem - may be a ModelItem or a newly instantiated object (from toolbox)
object droppedItem = DragDropHelper.GetDroppedObject(this, e, this.Context);
ModelItem canvasActivity = this.ModelItem;
canvasActivity.Properties["Children"].Collection.Add(droppedItem);
e.Handled = true;
DragDropHelper.SetDragDropCompletedEffects(e, DragDropEffects.Move);
base.OnDrop(e);
}
Any help please?
I realize this post is old but I just ran across this problem as well so thought I would post for anyone else who stumbles upon this. I found that adding your custom Activity library to the same binary path as your rehosted designer should do the trick.
Any ideas on how to pass parameters to Silverlight on startup from URL QueryString?
Thank You
One approach you can take is to expose a method that can be accessed from JavaScript. So in your xaml.cs file you need to add the following to your constructor:
this.Loaded += new RoutedEventHandler(Page_Loaded);
Then add the following event handler:
void Page_Loaded(object sender, RoutedEventArgs e)
{
HtmlPage.RegisterScriptableObject("YourControlName", this);
}
and:
[ScriptableMember]
public void YourMethod(string yourData)
{
// Do your stuff here
}
Then in the ascx or aspx page where your Silverlight control is instantiated add the following JavaScript:
var silverlightControl;
function onSilverlightLoad(sender, args) {
silverlightControl = sender.getHost();
var yourData = "some data";
silverlightControl.Content.YourControlName.YourMethod(yourData);
}
It does also mean that your Silverlight control has to be instantiated via the <object... tag rather than via <asp:Silverlight...
Although Chris's method will work, it's easier to pass startup information through Silverlight's initialization parameters feature.
If all you need to do is get at key-value pairs of the query string, there is a much simpler way using the HtmlPage class:
HtmlPage.Document.QueryString["your_key"];
I have a few users that are using a silverlight app that aren't recieving updates when a new release is published. Isn't this suppose to be automatic or perhaps I'm missing an option somewhere? I was also starting to think that maybe the XAP file is cached and I some how need to prevent that.
Any thoughts out there?
You need to write a few lines of code.
If you're familiar with 'one click' deployment then some of the options you're used to don't exist in Silverlight. You need to write the code yourself.
http://nerddawg.blogspot.com/2009/07/silverlight-out-of-browser-apps-how.html
private void Application_Startup(object sender, StartupEventArgs e)
{
this.RootVisual = new MainPage();
if (Application.Current.IsRunningOutOfBrowser)
{
Application.Current.CheckAndDownloadUpdateAsync();
}
and then in your App() constructor :
Application.Current.CheckAndDownloadUpdateCompleted +=
new CheckAndDownloadUpdateCompletedEventHandler(Current_CheckAndDownloadUpdateCompleted);
and an event handler :
void Current_CheckAndDownloadUpdateCompleted(object sender, CheckAndDownloadUpdateCompletedEventArgs e)
{
// http://nerddawg.blogspot.com/2009/07/silverlight-out-of-browser-apps-how.html
if (e.UpdateAvailable)
{
MessageBox.Show("The application has been updated! Please close and reopen it to load the new version.");
}
else if (e.Error != null && e.Error is PlatformNotSupportedException)
{
MessageBox.Show("An application update is available, " +
"but it requires a new version of Silverlight. " +
"Please contact tech support for further instructions.");
}
}
It only auto updates if the developer performs the CheckAndDownloadUpdateAsync() call. See updates: http://timheuer.com/blog/archive/2009/07/10/silverlight-3-released-what-is-new-and-changed.aspx#oob