There are two ways to pass data into a HTML web page from a WPF app, assuming you control the source code of the web page. Note that <%=coords%>
is an ASP.NET thing that passes information from the code behind to the front end on load and would require a lot more work to get working (there are easier options).
Method 1
If you only want one way communication (pass into the web page, but don't need to send anything back to WPF C#), you can pass the information in as a query string, then parse that when your application loads. This is really easy. Here is an example of a web page that takes in a URL with optional center
and zoom
parameters the look like this test.html?center=51.50632,-0.12714&zoom=15
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
<meta charset="utf-8" />
<meta charset="utf-8" http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
</head>
<body>
<div id='myMap' style='width: 100vw; height: 100vh;'></div>
<script>
var map;
function GetMap(){
//Default center/zoom values.
let center = new Microsoft.Maps.Location(0, 0);
let zoom = 1;
//Get the queryStringuery string of the URL.
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
//Extract center infromation from query string.
if (urlParams.has('center')) {
//Parse coordinates from the center parameter. Assume that string is in the format "latitude, longitude". Comma/space optional, must have atleast one.
let parts = urlParams.get('center').split(/[,\s]+/gi);
if(parts.length >= 2){
let lat = parseFloat(parts[0]);
let lon = parseFloat(parts[1]);
if(!isNaN(lat) && !isNaN(lat)){
center = new Microsoft.Maps.Location(lat, lon);
}
}
}
if (urlParams.has('zoom')) {
let z = parseInt(urlParams.get('zoom'));
if(!isNaN(z)){
zoom = z;
}
}
map = new Microsoft.Maps.Map('#myMap', {
center: center,
zoom: zoom
});
}
</script>
<script type='text/javascript' src='https://www.bing.com/api/maps/mapcontrol?callback=GetMap&key=[Your Bing Maps Key]' async defer></script>
</body>
</html>
The main limitations of this approach are:
- You can only pass as much information as the max URL length will allow (2083 characters).
- Information is only sent once, when the page loads. If you want to send new information, then the page has to be reloaded (inefficient, and can generate additional map sessions when using Bing Maps).
- No way to send information back to the WPF app.
Method 2
If you want to two-way communication, or want to avoid the limitations of method 1 you can wrap a web browser control in your application and make use of interoperability. Currently WPF provides WebView2 which allows you to embed the Edge browser into your application https://learn.microsoft.com/en-us/microsoft-edge/webview2/get-started/wpf Here is a great detailed blog post on how to do this: https://weblog.west-wind.com/posts/2021/Jan/26/Chromium-WebView2-Control-and-NET-to-JavaScript-Interop-Part-2
Alternatively, you can also use Chromium/CefSharp (https://cefsharp.github.io/) rather than WPF's WebView2 control (it likely will make your application a lot larger since it won't leverage the browser that's already installed on the system: https://dev.to/noseratio/comparing-process-working-sets-of-webview-based-windows-desktop-apps-5dkk).
Update: Method 3
You can read your HTML file as a string and do a find and replace on your placeholder. In the below example I've made the HTML file an embedded resource (likely what you will need to do if you want to ship this to others at some point). I called it mapPage.html
and have it in the root directory of the project. Add the html file to your project, go to properties and set build action to embedded resource. To read it you will need to include the namespace of your project in the file name path, in my case the namespace is SimpleWebBrowser
, thus the file name would when reading would be SimpleWebBrowser.mapPage.html
. Then in your C# code you could have a method like this:
private void LoadMap(double latitude, double longitude)
{
Assembly assembly = Assembly.GetExecutingAssembly();
using (var reader = new StreamReader(assembly.GetManifestResourceStream("SimpleWebBrowser.mapPage.html")))
{
var html = reader.ReadToEnd();
html = html.Replace("<%=coords%>", latitude + " " + longitude);
myBrowser.NavigateToString(html);
}
}
You HTML code would then handle the input like this:
<script type='text/javascript'>
var map;
var coords = '<%=coords%>';
function GetMap() {
//Default center.
var center = new Microsoft.Maps.Location(55, 0);
//Parse the coords string and get lat/lon values.
var parts = coords.split(' ');
if(parts.length >= 2){
let lat = parseFloat(parts[0]);
let lon = parseFloat(parts[1]);
if(!isNaN(lat) && !isNaN(lat)){
center = new Microsoft.Maps.Location(lat, lon);
}
}
map = new Microsoft.Maps.Map('#myMap', {center: });
...