c# - Script Notify för ms-appdata
Jag vill meddela min webbvy från en knapp i HTML-filen och utlösa JavaScript:
function notify(str) {
window.external.notify(str);
}
Händelsen fångad med wv_ScriptNotify(..., ...):
void wv_ScriptNotify(object sender, NotifyEventArgs e)
{
Color c=Colors.Red;
if (e.CallingUri.Scheme =="ms-appx-web" || e.CallingUri.Scheme == "ms-appdata")
{
if (e.Value.ToLower() == "blue") c = Colors.Blue;
else if (e.Value.ToLower() == "green") c = Colors.Green;
}
appendLog(string.Format("Response from script at '{0}': '{1}'", e.CallingUri, e.Value), c);
}
Jag satte html-filen på ms-appx-web och den fungerar bra, och jag inser att html-filen måste lagras i den lokala mappen. Så jag ändrade ms-appx-web:///.../index.html till ms-appdata:///local/.../index.html.
Jag har redan sökt i Microsofts forum och fått detta. I den tråden finns en lösning som använder resolver, men jag är fortfarande förvirrad, hur kan det meddela från JavaScript som att använda window.external.notify? Och vilken typ av händelse på C#-sidan kommer att fånga "notify" från JavaScript förutom "ScriptNotify"?
Uppdatera
Det finns en lösning härifrån, exempelvis att använda resolvern och det sades att använda ms-local-stream:// istället för ms-appdata://local så att jag fortfarande kan använda ScriptNotify-händelsen. Men tyvärr använder exemplet ms-appx vilket betyder att man använder InstalledLocation och inte LocalFolder.
Försökte googla och söka på MSDN:s webbplats efter dokumentation för ms-local-stream, men den enda dokumentationen är bara formatet för ms-local-stream utan något exempel som detta ms-local-stream://appname_KEY/folder/file.
Baserat på den dokumentationen gjorde jag ett exempel för att prova det:
public sealed class StreamUriWinRTResolver : IUriToStreamResolver
{
/// <summary>
/// The entry point for resolving a Uri to a stream.
/// </summary>
/// <param name="uri"></param>
/// <returns></returns>
public IAsyncOperation<IInputStream> UriToStreamAsync(Uri uri)
{
if (uri == null)
{
throw new Exception();
}
string path = uri.AbsolutePath;
// Because of the signature of this method, it can't use await, so we
// call into a separate helper method that can use the C# await pattern.
return getContent(path).AsAsyncOperation();
}
/// <summary>
/// Helper that maps the path to package content and resolves the Uri
/// Uses the C# await pattern to coordinate async operations
/// </summary>
private async Task<IInputStream> getContent(string path)
{
// We use a package folder as the source, but the same principle should apply
// when supplying content from other locations
try
{
// My package name is "WebViewResolver"
// The KEY is "MyTag"
string scheme = "ms-local-stream:///WebViewResolver_MyTag/local/MyFolderOnLocal" + path; // Invalid path
// string scheme = "ms-local-stream:///WebViewResolver_MyTag/MyFolderOnLocal" + path; // Invalid path
Uri localUri = new Uri(scheme);
StorageFile f = await StorageFile.GetFileFromApplicationUriAsync(localUri);
IRandomAccessStream stream = await f.OpenAsync(FileAccessMode.Read);
return stream.GetInputStreamAt(0);
}
catch (Exception) { throw new Exception("Invalid path"); }
}
}
Och inne i min MainPage.xaml.cs:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
// The 'Host' part of the URI for the ms-local-stream protocol needs to be a combination of the package name
// and an application-defined key, which identifies the specific resolver, in this case 'MyTag'.
Uri url = wv.BuildLocalStreamUri("MyTag", "index.html");
StreamUriWinRTResolver myResolver = new StreamUriWinRTResolver();
// Pass the resolver object to the navigate call.
wv.NavigateToLocalStreamUri(url, myResolver);
}
Det får alltid undantaget när det når raden StorageFile f=await StorageFile.GetFileFromApplicationUriAsync(localUri);.
Om någon någonsin har haft detta problem och redan löst det, vänligen ge råd.
Svar #1
Efter att ha felsökt det, hittade jag något intressant, BuildLocalStreamUri-delen gör redan ms-local-stream automatiskt.
Jag gjorde några ändringar i getContent-metoden i StreamUriWinRTResolver-klassen:
public sealed class StreamUriWinRTResolver : IUriToStreamResolver
{
/// <summary>
/// The entry point for resolving a Uri to a stream.
/// </summary>
/// <param name="uri"></param>
/// <returns></returns>
public IAsyncOperation<IInputStream> UriToStreamAsync(Uri uri)
{
if (uri == null)
{
throw new Exception();
}
string path = uri.AbsolutePath;
// Because of the signature of this method, it can't use await, so we
// call into a separate helper method that can use the C# await pattern.
return getContent(path).AsAsyncOperation();
}
/// <summary>
/// Helper that maps the path to package content and resolves the Uri
/// Uses the C# await pattern to coordinate async operations
/// </summary>
private async Task<IInputStream> getContent(string path)
{
// We use a package folder as the source, but the same principle should apply
// when supplying content from other locations
try
{
// Don't use "ms-appdata:///" on the scheme string, because inside the path
// will contain "/local/MyFolderOnLocal/index.html"
string scheme = "ms-appdata://" + path;
Uri localUri = new Uri(scheme);
StorageFile f = await StorageFile.GetFileFromApplicationUriAsync(localUri);
IRandomAccessStream stream = await f.OpenAsync(FileAccessMode.Read);
return stream.GetInputStreamAt(0);
}
catch (Exception) { throw new Exception("Invalid path"); }
}
}
Ändra filvägen i MainPage.xaml.cs:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
// The 'Host' part of the URI for the ms-local-stream protocol needs to be a combination of the package name
// and an application-defined key, which identifies the specific resolver, in this case 'MyTag'.
Uri url = wv.BuildLocalStreamUri("MyTag", "/local/MyFolderOnLocal/index.html");
StreamUriWinRTResolver myResolver = new StreamUriWinRTResolver();
// Pass the resolver object to the navigate call.
wv.NavigateToLocalStreamUri(url, myResolver);
wv.ScriptNotify += wv_ScriptNotify;
}
protected override void wv_ScriptNotify(object sender, NavigationEventArgs e)
{
if (e.CallingUri.Scheme == "ms-local-stream")
{
// Do your work here...
}
}
