简体   繁体   English

如何在 WPF 数据网格中呈现 HTML 或 markdown?

[英]How can I render HTML or markdown in a WPF datagrid?

Is there a way to render/show HTML (or Markdown) in a .NET Core WPF Datagrid column / cell?有没有办法在 .NET Core WPF Datagrid 列/单元格中渲染/显示 HTML(或 Markdown)?

I have some text in a database which I would like to add some formatting options to.我在数据库中有一些文本,我想向其中添加一些格式选项。 I was thinking to add the possibility to format it using markdown.我正在考虑添加使用 markdown 对其进行格式化的可能性。

This text then is displayed in a datagrid using itemsource = List<myobject> , and I would like to have it displayed formatted in the datagrid column/cell.然后,此文本使用itemsource = List<myobject>显示在数据网格中,我希望将其格式化显示在数据网格列/单元格中。

So I used Markdig to generate HTML from the text in the database.所以我使用Markdig从数据库中的文本生成HTML。 This gives me something like:这给了我类似的东西:

<p>This is a text with some <em>emphasis</em></p>

And this should be displayed like:这应该显示为:

This is a text with some emphasis这是一个有一定重点的文字

But then I get stuck.但后来我卡住了。 It seems like HTML is something alien to WPF. HTML 似乎与 WPF 不同。

It's possible to do this with WPF's WebBrowser control in a DataGridTemplateColumn.可以使用 DataGridTemplateColumn 中的 WPF 的WebBrowser 控件来执行此操作。 Some sample code is below.一些示例代码如下。

To get the WebBrowser to display an HTML string you have to call NavigateToString.要让 WebBrowser 显示 HTML 字符串,您必须调用 NavigateToString。 I've done this using an attached property as described in another Stack Overflow answer .我已经使用附加属性完成了此操作,如另一个 Stack Overflow 答案中所述。

I've also done some work to remove the disabled scrollbars that the control will put in a cell by default, even if the content fits.我还做了一些工作来删除控件默认放置在单元格中的禁用滚动条,即使内容适合。 I've used CSS styling to do this, but it's a little hacky.我已经使用 CSS 样式来做到这一点,但它有点 hacky。

Note that we are warned that the WebBrowser control is quite heavyweight in terms of memory usage, so you probably wouldn't want to do it this way in a grid with a lot of rows.请注意,我们被警告说,WebBrowser 控件在 memory 的使用方面非常重要,因此您可能不希望在有很多行的网格中这样做。

在此处输入图像描述

C#: C#:

using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;

namespace WpfApp14
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.CreateProducts();
            this.MyDataGrid.ItemsSource = Products;
        }

        public ObservableCollection<Product> Products { get; set; }

        private void CreateProducts()
        {
            Products = new ObservableCollection<Product>
            {
                new Product{ID = 1, Html = "HTML with no formatting"},
                new Product{ID = 2, Html= "<h1>This is a <i>test</i> header</h1>"},
                new Product{ID = 3, Html="<p>This is a text with some <em>emphasis</em></p>"},
                new Product{ID = 4, Html="<ul><li>Product 1</li><li>Product 2</li><li>Product 3</li></ul>"}
            };
        }
    }

    public class Product : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private int id;
        public int ID
        {
            get { return id; }
            set
            {
                id = value;
                PropertyChanged?.Invoke(this,
                   new PropertyChangedEventArgs(nameof(ID)));
            }
        }

        private string html;
        public string Html
        {
            get { return html; }
            set
            {
                html = RemoveScrollbars(value);
                PropertyChanged?.Invoke(this,
                    new PropertyChangedEventArgs(nameof(Html)));
            }
        }

        private string RemoveScrollbars(string html)
        {
            string before = "<head><style>body{overflow:hidden;}</style></head><body>";
            string after = "</body>";
            return before + html + after;
        }
    }

    public static class BrowserBehavior
    {
        public static readonly DependencyProperty HtmlProperty = DependencyProperty.RegisterAttached(
            "Html",
            typeof(string),
            typeof(BrowserBehavior),
            new FrameworkPropertyMetadata(OnHtmlChanged));

        [AttachedPropertyBrowsableForType(typeof(WebBrowser))]
        public static string GetHtml(WebBrowser d)
        {
            return (string)d.GetValue(HtmlProperty);
        }

        public static void SetHtml(WebBrowser d, string value)
        {
            d.SetValue(HtmlProperty, value);
        }

        static void OnHtmlChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            WebBrowser wb = d as WebBrowser;
            if (wb != null)
                wb.NavigateToString(e.NewValue as string);
        }
    }
}

XAML: XAML:

<Window x:Class="WpfApp14.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp14"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <DataGrid x:Name="MyDataGrid" AutoGenerateColumns="False" CanUserAddRows="False">
        <DataGrid.Columns>
            <DataGridTextColumn Binding="{Binding ID}"/>
            <DataGridTemplateColumn Width="300">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <WebBrowser local:BrowserBehavior.Html="{Binding Html}" Height="90"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>
</Window>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM