如何处理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
相关产品推荐
相关产品推荐

