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

如何处理BitmapImage的数据绑定与序列化?JsonIgnore失效问题

问题解决方案

1. 修复[JsonIgnore]不生效问题

你看到MyImageBitmap被序列化,是因为你使用的[JsonIgnore]可能来自System.Text.Json命名空间,而Newtonsoft.Json需要用它专属的特性。修改代码,明确指定Newtonsoft的JsonIgnore:

using Newtonsoft.Json; // 确保引入该命名空间

public class MyObject
{
    // ...其他属性...

    [JsonIgnore] // 该特性会被Newtonsoft.Json正确识别
    public BitmapImage? MyImageBitmap { get; set; }
}

如果项目同时引用了System.Text.Json和Newtonsoft.Json,建议直接写全称避免混淆:

[Newtonsoft.Json.JsonIgnore]
public BitmapImage? MyImageBitmap { get; set; }

2. 重构MyImageBase64属性,实现反序列化自动转换为BitmapImage

你当前的MyImageBase64 getter存在递归调用(if (MyImageBase64 != null)会再次触发getter),会导致栈溢出。需要用私有字段存储Base64值,把转换逻辑移到setter中:

public class MyObject
{
    public decimal MyDeciaml { get; set; }

    private string? _myImageBase64;
    public string? MyImageBase64
    {
        get => _myImageBase64;
        set
        {
            _myImageBase64 = value;
            // 当Base64值更新时,自动转换为BitmapImage
            if (!string.IsNullOrEmpty(_myImageBase64))
            {
                byte[] imageBytes = Convert.FromBase64String(_myImageBase64);
                using (MemoryStream stream = new MemoryStream(imageBytes))
                {
                    BitmapImage bitmapImage = new BitmapImage();
                    bitmapImage.BeginInit();
                    bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
                    bitmapImage.StreamSource = stream;
                    bitmapImage.EndInit();
                    bitmapImage.Freeze(); // 冻结后可在非UI线程安全使用
                    MyImageBitmap = bitmapImage;
                }
            }
            else
            {
                MyImageBitmap = null;
            }
        }
    }

    [Newtonsoft.Json.JsonIgnore]
    public BitmapImage? MyImageBitmap { get; set; }
}

反序列化时,Newtonsoft.Json会自动设置MyImageBase64的值,触发setter生成对应的MyImageBitmap,无需额外处理。

3. 直接绑定Base64字符串到Image控件

可以通过实现IValueConverter,在XAML绑定过程中直接将Base64字符串转为BitmapImage,这样无需保留MyImageBitmap属性:

第一步:实现转换器

using System;
using System.Globalization;
using System.IO;
using System.Windows.Data;
using System.Windows.Media.Imaging;

public class Base64ToBitmapImageConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is not string base64String || string.IsNullOrEmpty(base64String))
            return null;

        try
        {
            byte[] imageBytes = Convert.FromBase64String(base64String);
            using (MemoryStream stream = new MemoryStream(imageBytes))
            {
                BitmapImage bitmapImage = new BitmapImage();
                bitmapImage.BeginInit();
                bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
                bitmapImage.StreamSource = stream;
                bitmapImage.EndInit();
                bitmapImage.Freeze();
                return bitmapImage;
            }
        }
        catch
        {
            // 转换失败时可返回默认图片或null
            return null;
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        // 无需反向转换时抛出异常或返回null
        throw new NotImplementedException();
    }
}

第二步:在XAML中引用转换器

在Window/UserControl的Resources中声明转换器:

<Window.Resources>
    <local:Base64ToBitmapImageConverter x:Key="Base64ToImageConverter" />
</Window.Resources>

(注意local是你的项目命名空间,需提前声明,如xmlns:local="clr-namespace:YourProjectName")

第三步:修改ListBox绑定

直接绑定MyImageBase64并指定转换器:

<ListBox ItemsSource="{Binding MyObjects}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <Grid>
                    <Image x:Name="myImage"
                           Source="{Binding MyImageBase64, Converter={StaticResource Base64ToImageConverter}}"
                           VerticalAlignment="Center"
                           HorizontalAlignment="Center"
                           Width="Auto"
                           Height="Auto" />
                </Grid>
                <TextBlock Text="{Binding MyDeciaml }" />
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

此时MyObject类可简化为:

public class MyObject
{
    public decimal MyDeciaml { get; set; }
    public string? MyImageBase64 { get; set; }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 08:23:10