Displaying HTML in WPF using MVVM

后端 未结 3 1548
爱一瞬间的悲伤
爱一瞬间的悲伤 2021-01-12 02:43

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. HT

相关标签:
3条回答
  • 2021-01-12 03:16

    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>
    
    0 讨论(0)
  • 2021-01-12 03:25

    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);
                }
            }
        }
    }
    
    0 讨论(0)
  • 2021-01-12 03:34

    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.

    0 讨论(0)
提交回复
热议问题