Xamarin中如何将选取的图片存入本地SQLite并在其他页面展示
实现方案
方案1:存储本地文件路径(推荐,无需手动处理Stream,性能最优)
这是符合你需求的优化方案,核心逻辑是把选中的图片复制到APP私有沙盒目录,数据库只存储文件的绝对路径,后续直接用路径绑定图片,不需要额外格式转换,数据库体积和查询速度都远优于存二进制的方案。
步骤1:修改Post模型类
新增字符串类型的图片路径字段即可:
public class Post { [PrimaryKey, AutoIncrement] public int Id { get; set; } public string Title { get; set; } public string Experience { get; set; } public string Location { get; set; } // 新增图片本地路径存储字段 public string ImagePath { get; set; } }
步骤2:媒体选择后存储图片到本地
拿到MediaPicker返回的FileResult后直接复制到本地目录,框架封装的复制方法不需要你手动操作Stream读写:
// 拍照/图库选图完成后的处理逻辑 private async void OnMediaSelected(FileResult result) { if (result == null) return; // 生成唯一的本地存储路径,避免文件名重复 var localPath = Path.Combine(FileSystem.AppDataDirectory, $"{Guid.NewGuid()}{Path.GetExtension(result.FileName)}"); // 直接复制文件到本地 using (var sourceStream = await result.OpenReadAsync()) using (var destStream = File.Create(localPath)) { await sourceStream.CopyToAsync(destStream); } // 组装Post对象 var newPost = new Post { Title = TitleEntry.Text, Experience = ExperienceEditor.Text, Location = LocationLabel.Text, ImagePath = localPath }; // 调用你已有的SQLite插入逻辑即可 await _db.InsertAsync(newPost); }
步骤3:ListView绑定图片显示
Xamarin.Forms的Image控件原生支持本地文件路径作为Source,直接绑定即可,不需要额外转换:
<ListView ItemsSource="{Binding PostList}"> <ListView.ItemTemplate> <DataTemplate> <ViewCell> <StackLayout Orientation="Horizontal" Padding="10"> <Image Source="{Binding ImagePath}" WidthRequest="80" HeightRequest="80" Aspect="AspectFill"/> <StackLayout Padding="10,0"> <Label Text="{Binding Title}" FontAttributes="Bold" FontSize="Medium"/> <Label Text="{Binding Location}" FontSize="Small" TextColor="Gray"/> <Label Text="{Binding Experience}" MaxLines="2" LineBreakMode="TailTruncation" FontSize="Small"/> </StackLayout> </StackLayout> </ViewCell> </DataTemplate> </ListView.ItemTemplate> </ListView>
方案2:直接存储二进制到SQLite
如果你确实需要把图片完整存在数据库中,不需要单独保留本地文件,按以下步骤实现:
步骤1:修改Post模型类
新增byte数组类型的字段,SQLite会自动映射为BLOB类型存储:
public class Post { [PrimaryKey, AutoIncrement] public int Id { get; set; } public string Title { get; set; } public string Experience { get; set; } public string Location { get; set; } // 存储图片二进制数据 public byte[] ImageData { get; set; } }
步骤2:图片转二进制入库
private async void OnMediaSelected(FileResult result) { if (result == null) return; byte[] imageBytes; using (var stream = await result.OpenReadAsync()) using (var memoryStream = new MemoryStream()) { await stream.CopyToAsync(memoryStream); imageBytes = memoryStream.ToArray(); } var newPost = new Post { Title = TitleEntry.Text, Experience = ExperienceEditor.Text, Location = LocationLabel.Text, ImageData = imageBytes }; await _db.InsertAsync(newPost); }
步骤3:绑定到ListView显示
需要新增一个值转换器,把byte数组转为ImageSource:
首先创建转换器类:
public class ByteArrayToImageSourceConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value is byte[] bytes) { return ImageSource.FromStream(() => new MemoryStream(bytes)); } return null; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } }
然后在XAML中注册转换器并使用:
<ContentPage.Resources> <local:ByteArrayToImageSourceConverter x:Key="ByteToImageConverter"/> </ContentPage.Resources> <!-- ListView的ItemTemplate中Image的绑定写法 --> <Image Source="{Binding ImageData, Converter={StaticResource ByteToImageConverter}}" WidthRequest="80" HeightRequest="80" Aspect="AspectFill"/>
注意事项
- 优先选择方案1,存储路径的方式会让SQLite数据库体积比存二进制小30%以上,查询、加载速度都更快
- 用方案1的话,删除Post记录时需要同步删除对应的本地图片,新增一行
File.Delete(post.ImagePath)即可
内容的提问来源于stack exchange,提问作者Patrick89
相关产品推荐
相关产品推荐

