如何在C#中为Markdig设置根目录以加载相对路径图片?
解决Markdig.Wpf渲染Markdown图片相对路径问题
要让Markdig识别项目根目录下的相对路径图片,你可以通过自定义图片渲染器修改图片路径,将相对路径转换为基于项目根目录的绝对路径,具体步骤如下:
1. 自定义ImageRenderer
创建继承自Markdig.Wpf.ImageRenderer的自定义渲染器,在渲染图片时替换相对路径为绝对路径:
public class CustomImageRenderer : Markdig.Wpf.ImageRenderer { private readonly string _baseDirectory; public CustomImageRenderer(TextBlockRenderer renderer, string baseDirectory) : base(renderer) { _baseDirectory = baseDirectory; } protected override void Render(Markdig.Syntax.Inlines.LinkInline link) { if (link.IsImage) { var imagePath = link.Url; // 仅处理相对路径 if (!Path.IsPathRooted(imagePath)) { // 组合项目根目录与相对路径,生成绝对路径 var absolutePath = Path.GetFullPath(Path.Combine(_baseDirectory, imagePath)); // 转换为WPF可识别的Uri格式 link.Url = new Uri(absolutePath).ToString(); } } // 调用基类完成后续渲染 base.Render(link); } }
2. 修改Pipeline构建逻辑
修改BuildPipeline方法,传入项目根目录,并替换默认的图片渲染器为自定义实现:
private static Markdig.MarkdownPipeline BuildPipeline(string baseDirectory) { var pipelineBuilder = new Markdig.MarkdownPipelineBuilder() .UseSupportedExtensions(); var pipeline = pipelineBuilder.Build(); // 找到WpfRenderer并替换ImageRenderer var wpfRenderer = pipeline.Renderers.Find<Markdig.Wpf.WpfRenderer>(); if (wpfRenderer != null) { var defaultImageRenderer = wpfRenderer.ObjectRenderers.Find<Markdig.Wpf.ImageRenderer>(); if (defaultImageRenderer != null) { wpfRenderer.ObjectRenderers.Remove(defaultImageRenderer); } wpfRenderer.ObjectRenderers.Add(new CustomImageRenderer(wpfRenderer.TextBlockRenderer, baseDirectory)); } return pipeline; }
3. 调用修改后的Pipeline
在加载Markdown时,将项目根目录传入BuildPipeline:
private void OnReadmeLoaded(object sender, RoutedEventArgs e) { var projectDirectory = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "..\\..\\..\\")); var readmePath = Path.Combine(projectDirectory, "README.md"); if (File.Exists(readmePath)) { var markdown = File.ReadAllText(readmePath); // 传入项目根目录构建Pipeline var xaml = Markdig.Wpf.Markdown.ToXaml(markdown, BuildPipeline(projectDirectory)); using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(xaml))) { using (var reader = new XamlXmlReader(stream, new MyXamlSchemaContext())) { if (XamlReader.Load(reader) is FlowDocument document) { Viewer.Document = document; } } } } else { MessageBox.Show("Markdown file not found: " + readmePath); } }
原理说明
Markdig.Wpf默认直接使用Markdown中的相对路径生成Image控件的Source,但WPF无法直接识别基于项目根目录的相对路径。自定义渲染器会在图片渲染前,将相对路径转换为绝对Uri,让WPF能够正确定位并加载图片文件。
内容的提问来源于stack exchange,提问作者Kenny Cason




