11

I have HTML-Source string saved in SQL Server table called "Report" in HTMLReport field (field type is NTEXT). Now I need to display that stored HTML into WPF Window. HTML tags and inline-CSS need to be interpreted on this WPF Window.

Can someone help me to complete this code?

HTMLView.xaml

  <Window x:Class="MyProject.HTMLView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
    Title="HTML View" Height="454" Width="787"
    >
  <Grid Name="grid1">
    <WindowsFormsHost>

    <wf:RichTextBox x:Name="reportHTML" Text="{Binding DisplayHTML, Mode=OneWay}"/>

       <!-- How do i bind dispaly HTML page here-->

    </WindowsFormsHost>
  </Grid>
</Window>

HTMLViewModel.cs

  namespace MyProject
  {
    public class HTMLViewModel: ViewModelBase
    {
      public HTMLViewModel()
      {
            //Reading from SQL Server table 
            //SELECT HTMLReport FROM Report WHERE ID=123
            //OK, I have HTMLString from database over here
            //Now I am assigning that to DisplayHTML Property

           DisplayHTML ="<table><tr><td><b>This text should be in table with bold fond </b></td></tr></table>";
      }

      private string _displayHTML;
      public string DisplayHTML
      {
        get
        {
            return _displayHTML;
        }

        set
        {
            if (_displayHTML!= value)
            {
                _displayHTML= value;
                OnPropertyChanged("DisplayHTML");
            }
        }
    }
  }

3 Answers 3

5

You'll probably want to use a WPF RichTextBox instead of the Winforms one. Note that its Document property is of type FlowDocument. Since you have HTML, you will need a way to convert HTML to a FlowDocument. This question and answer describe a way to do the conversion.

Sign up to request clarification or add additional context in comments.

Comments

1

I created a control based on this article:

http://blogs.msdn.com/b/ryanvog/archive/2009/01/20/clipping-legacy-content-hosted-inside-a-wpf-scrolling-region.aspx

...

public class ScrollableWebBrowser : WindowsFormsHost
{
    [DllImport("GDI32.DLL", EntryPoint = "CreateRectRgn")]
    private static extern IntPtr CreateRectRgn(Int32 x1, Int32 y1, Int32 x2, Int32 y2);

    [DllImport("User32.dll", SetLastError = true)]
    private static extern Int32 SetWindowRgn(IntPtr hWnd, IntPtr hRgn, Boolean bRedraw);

    private Int32 _topLeftX = -1;
    private Int32 _topLeftY = -1;
    private Int32 _bottomRightX = -1;
    private Int32 _bottomRightY = -1;
    bool _disposed = false;

    public static readonly DependencyProperty HtmlProperty = DependencyProperty.Register("Html", typeof(string), typeof(ScrollableWebBrowser), new PropertyMetadata(OnHtmlChanged));
    public string Html
    {
        get { return (string)GetValue(HtmlProperty); }
        set { SetValue(HtmlProperty, value); }
    }

    public ScrollableWebBrowser()
    {
        EventManager.RegisterClassHandler(typeof(ScrollViewer), ScrollViewer.ScrollChangedEvent, new ScrollChangedEventHandler(ScrollHandler));
    }

    static void OnHtmlChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ((ScrollableWebBrowser)d).UpdateWebBrowser();
    }

    void UpdateWebBrowser()
    {
        if (this.Child == null)
            this.Child = new System.Windows.Forms.WebBrowser();

        System.Windows.Forms.WebBrowser browser = this.Child as System.Windows.Forms.WebBrowser;
        if (browser != null)
            browser.DocumentText = System.Net.WebUtility.HtmlDecode(Html);
    }

    private void ScrollHandler(Object sender, ScrollChangedEventArgs ea)
    {
        PresentationSource presentationSource = HwndSource.FromVisual(this);
        if (presentationSource == null)
            return;

        Visual rootVisual = presentationSource.RootVisual;
        if (rootVisual == null)
            return;

        ScrollViewer scrollViewer = (ScrollViewer)sender;
        if (!scrollViewer.IsDescendantOf(rootVisual))
            return;

        Rect hostRect = this.TransformToAncestor(rootVisual).TransformBounds(new Rect(this.Padding.Left, this.Padding.Right, this.RenderSize.Width, this.RenderSize.Height));
        Rect intersectRect = Rect.Intersect(scrollViewer.TransformToAncestor(rootVisual).TransformBounds(new Rect(0, 0, scrollViewer.ViewportWidth, scrollViewer.ViewportHeight)), hostRect);
        Int32 topLeftX = 0;
        Int32 topLeftY = 0;
        Int32 bottomRightX = 0;
        Int32 bottomRightY = 0;

        if (intersectRect != Rect.Empty)
        {
            topLeftX = (Int32)(intersectRect.TopLeft.X - hostRect.TopLeft.X);
            topLeftY = (Int32)(intersectRect.TopLeft.Y - hostRect.TopLeft.Y);
            bottomRightX = (Int32)(intersectRect.BottomRight.X - hostRect.TopLeft.X);
            bottomRightY = (Int32)(intersectRect.BottomRight.Y - hostRect.TopLeft.Y);
        }

        if (_topLeftX != topLeftX || _topLeftY != topLeftY || _bottomRightX != bottomRightX || _bottomRightY != bottomRightY)
        {
            _topLeftX = topLeftX;
            _topLeftY = topLeftY;
            _bottomRightX = bottomRightX;
            _bottomRightY = bottomRightY;

            SetWindowRgn(this.Handle, CreateRectRgn(_topLeftX, _topLeftY, _bottomRightX, _bottomRightY), true);
        }
    }

    protected override void Dispose(Boolean disposing)
    {
        if (disposing)
        {
            try
            {
                if (!_disposed && this.Child != null)
                    this.Child.Dispose();

                _disposed = true;
            }
            finally
            {
                base.Dispose(disposing);
            }
        }
    }
}

Comments

0

I would recommend to use Exceed WPF ToolKit RichTextBox which can bind to string representation of Xaml markup using Text property. For converting Html to Xaml I used HtmlToXamlConverter nuget package. HtmlToXamlConverter.ConvertHtmlToXaml(html, false)

If you want to display it as TextBlock as me here are some styles:

Style TargetType="RichTextBox" x:Key="RichTextBoxStyle">
        <Setter Property="FontFamily" Value="{StaticResource OverpassRegular}" />
        <Setter Property="Foreground" Value="White" />
        <Setter Property="FontWeight" Value="DemiBold" />
        <Setter Property="Opacity" Value="0.95" />
        <Setter Property="Background" Value="Transparent" />
        <Setter Property="CaretBrush" Value="White" />
    </Style>

    <Style x:Key="RichTextBoxAsTextBlock" TargetType="xctk:RichTextBox" BasedOn="{StaticResource RichTextBoxStyle}">
        <Setter Property="Cursor" Value="Arrow" />
        <Setter Property="SelectionBrush" Value="Transparent" />
        <Setter Property="IsReadOnly" Value="True" />
        <Setter Property="BorderThickness" Value="0" />
        <Setter Property="BorderBrush" Value="Transparent" />
        <Setter Property="FontWeight" Value="Normal" />
        <Setter Property="Foreground">
            <Setter.Value>
                <SolidColorBrush Color="{DynamicResource Primary.ForegroundColor}" />
            </Setter.Value>
        </Setter>
        <Setter Property="TextFormatter">
            <Setter.Value>
                <xctk:XamlFormatter />
            </Setter.Value>
        </Setter>
    </Style>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.