0

I have a UWP app where the view contains a WebView. In my ViewModel, I have two variables, one that contains a URI and another that contains HTML content.

I need to be able to navigate to the URI OR display the HTML content, depending on the state of a ToggleButton.

I can bind the Source property of the WebView to navigate to a URI but I don't know how to load the HTML content in the WebView.

I know that there is a method WebView.NavigateToString(string) but don't know how to call this from my ViewModel. I've read that you should call this from the code behind of the view but my view can't see the content that's in my ViewModel.

The obvious way would be to get a reference to the WebView from my ViewModel but I don't know how to do this and it spoils the separation of the MVVM pattern.

Can anyone suggest a solution?

public class MainPageViewModel : INotifyPropertyChanged
{
    // These properties all observable - notification omitted
    // for brevity
    public bool UseUri { get; set; }
    public string HtmlContent { get; set; }
    public Uri WebUri { get; set; }
}
public sealed partial class MainPage : Page
{
    public MainPageViewModel ViewModel { get; }

    public MainPage()
    {
        this.InitializeComponent();

        ViewModel = new MainPageViewModel();
    }
}
<Page
    x:Class="ReaderZero.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
        <WebView Source="{x:Bind Path=ViewModel.SelectedEntry.Uri, Mode=OneWay}" />
</Page>
Mog0
  • 1,689
  • 1
  • 16
  • 40
  • Possible duplicate: [Display local html file content in UWP WebView](https://stackoverflow.com/a/42419169/12888024). – aepot Sep 27 '20 at 23:56
  • Not a duplicate - That is displaying local files, this is content from a variable, which is totally different, unless you're suggesting that I create temporary files every time I need to display content! – Mog0 Sep 28 '20 at 15:01
  • Ok. But maybe that's the only solution, I don't know. – aepot Sep 28 '20 at 16:25
  • Hi @Mog0, have you tested the following solution. Does it work in your side? – Nico Zhu Sep 29 '20 at 01:23
  • 1
    Hi @Nico Zhu, Sorry, I've not yet had chance to try it but it does look like what I need. This is a personal project that's mostly weekends but I'll try it as soon as I get the chance. – Mog0 Sep 29 '20 at 07:14

1 Answers1

2

I know that there is a method WebView.NavigateToString(string) but don't know how to call this from my ViewModel. I've read that you should call this from the code behind of the view but my view can't see the content that's in my ViewModel.

For this scenario, you could refer Binding HTML to a WebView with Attached Properties blog to make WebViewExtention like following.

public class MyWebViewExtention
{
    public static readonly DependencyProperty HtmlSourceProperty =
           DependencyProperty.RegisterAttached("HtmlSource", typeof(string), typeof(MyWebViewExtention), new PropertyMetadata("", OnHtmlSourceChanged));
    public static string GetHtmlSource(DependencyObject obj) { return (string)obj.GetValue(HtmlSourceProperty); }
    public static void SetHtmlSource(DependencyObject obj, string value) { obj.SetValue(HtmlSourceProperty, value); }
    private static void OnHtmlSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        WebView webView = d as WebView;
        if (webView != null)
        {
            webView.NavigateToString((string)e.NewValue);
        }
    }
 }

Usage

<WebView x:Name="webView" local:MyWebViewExtention.HtmlSource="{x:Bind HtmlContent ,Mode=OneWay}">

Base on above, you could make two WebViews and bind the Visibility with ToggleButton IsChecked property. And this will not spoil the separation of the MVVM pattern

Nico Zhu
  • 32,367
  • 2
  • 15
  • 36
  • 1
    Thanks @Nico that seems to work brilliantly. Also really appreciate the links to the documentation so I can understand the code better in case I need to tweak it or do this elsewhere. Superb answer, wish I could give more than one vote up ☺ – Mog0 Oct 04 '20 at 15:32