Reputation: 569
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?
<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>
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");
}
}
}
}
Upvotes: 11
Views: 32593
Reputation: 3570
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>
Upvotes: 0
Reputation: 344
I created a control based on this article:
...
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);
}
}
}
}
Upvotes: 1
Reputation: 6103
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.
Upvotes: 5