You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为RichTextBox添加带ResizeAdorner的图片时消失,该如何解决?

为RichTextBox的FlowDocument添加带ResizeAdorner的图片

问题说明

向RichTextBox的FlowDocument中添加图片时,直接用ResizeAdorner包裹Image并放入BlockUIContainer后图片消失,原始可运行代码与失效代码如下:

原始可正常运行的代码

public ICommand ImageCommand { get; set; }
private bool CanImageExecute(object parameter) => true;
private void OnImageExecute(object parameter)
{
    var file = new Microsoft.Win32.OpenFileDialog();
    file.ShowDialog();
    if(System.IO.Path.GetExtension(file.FileName).ToLower() is ".png" || System.IO.Path.GetExtension(file.FileName).ToLower() is ".jpg")
    {
        var BitMapImage = new BitmapImage();
        BitMapImage.BeginInit();
        BitMapImage.StreamSource = new MemoryStream(File.ReadAllBytes(file.FileName));
        BitMapImage.EndInit();

        if (_TextSelected is null) return;
        if (TextSelected.End.Paragraph is null) FileSystem.FileCurent.Blocks.Add(new Paragraph());

        FileSystem.FileCurent.Blocks.InsertBefore(TextSelected.End.Paragraph, new BlockUIContainer(new Image { Source = BitMapImage}));
    }
}

包裹ResizeAdorner后失效的代码

public ICommand ImageCommand { get; set; }
private bool CanImageExecute(object parameter) => true;
private void OnImageExecute(object parameter)
{
    var file = new Microsoft.Win32.OpenFileDialog();
    file.ShowDialog();
    if(System.IO.Path.GetExtension(file.FileName).ToLower() is ".png" || System.IO.Path.GetExtension(file.FileName).ToLower() is ".jpg")
    {
        var BitMapImage = new BitmapImage();
        BitMapImage.BeginInit();
        BitMapImage.StreamSource = new MemoryStream(File.ReadAllBytes(file.FileName));
        BitMapImage.EndInit();

        if (_TextSelected is null) return;
        if (TextSelected.End.Paragraph is null) FileSystem.FileCurent.Blocks.Add(new Paragraph());

        FileSystem.FileCurent.Blocks.InsertBefore(TextSelected.End.Paragraph, new BlockUIContainer(new ResizeAdorner(new Image { Source = BitMapImage })));
    }
}

问题原因

ResizeAdorner属于**Adorner(装饰器)**类型,它不是常规UIElement,不能直接作为BlockUIContainer的内容。Adorner的作用是附加到已存在的UIElement上,且必须通过AdornerLayer来管理,而非直接替换原控件作为容器内容。

正确实现方案

需要先将Image添加到FlowDocument中,等Image加载到可视化树后,再为其添加ResizeAdorner。具体实现代码如下:

public ICommand ImageCommand { get; set; }
private bool CanImageExecute(object parameter) => true;
private void OnImageExecute(object parameter)
{
    var file = new Microsoft.Win32.OpenFileDialog();
    if (file.ShowDialog() != true) return; // 处理用户取消选择文件的情况

    var extension = System.IO.Path.GetExtension(file.FileName).ToLower();
    if (extension is ".png" or ".jpg")
    {
        var bitmapImage = new BitmapImage();
        bitmapImage.BeginInit();
        bitmapImage.StreamSource = new MemoryStream(File.ReadAllBytes(file.FileName));
        bitmapImage.CacheOption = BitmapCacheOption.OnLoad; // 防止图片文件被锁定
        bitmapImage.EndInit();

        if (_TextSelected is null) return;
        if (TextSelected.End.Paragraph is null) 
            FileSystem.FileCurent.Blocks.Add(new Paragraph());

        var image = new Image { Source = bitmapImage };
        // 监听Loaded事件,确保控件已进入可视化树再添加装饰器
        image.Loaded += (s, e) =>
        {
            var adornerLayer = AdornerLayer.GetAdornerLayer(image);
            if (adornerLayer != null)
            {
                adornerLayer.Add(new ResizeAdorner(image));
            }
        };

        FileSystem.FileCurent.Blocks.InsertBefore(TextSelected.End.Paragraph, new BlockUIContainer(image));
    }
}

额外注意事项

  • 添加BitmapCacheOption.OnLoad:避免程序锁定图片文件,导致无法删除或修改文件
  • 增加对话框确认判断:处理用户取消选择文件的场景
  • 延迟添加Adorner:必须在Image加载完成后获取AdornerLayer,否则GetAdornerLayer会返回null

内容的提问来源于stack exchange,提问作者Vladlen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 01:42:25