WPF .NET 6.0中更新Image Source不显示问题求助
问题描述
我正在开发一款应用,需实现显示代码生成图片的功能。我能生成图片并创建新Source,但在ViewModel中替换后图片无法显示。为复现问题编写了最小化测试程序,请问我遗漏了什么?我之前有个使用代码后台的类似应用,通过Dispatcher的Invoke方法替换新BitmapImage作为图片Source是有效的。
ViewModel代码
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Windows; using System.Windows.Input; using System.Windows.Media.Imaging; using System.Windows.Threading; namespace TestImgs.ViewModels; public class MainViewModel : ObservableObject { public BitmapImage RedImg { get; set; } = null; public BitmapImage BlueImg { get; set; } = null; public BitmapImage GreenImg { get; set; } = null; public ICommand RenderCmd { get; set; } private readonly Dispatcher dispatcher; public MainViewModel() { dispatcher = Application.Current.Dispatcher; RenderCmd = new RelayCommand(Render); } public void Render() { dispatcher.Invoke(() => RedImg = GetSolidImg(Color.Red)); dispatcher.Invoke(() => BlueImg = GetSolidImg(Color.Blue)); dispatcher.Invoke(() => GreenImg = GetSolidImg(Color.Green)); } private static BitmapImage GetSolidImg(Color color) { var bmp = new Bitmap(1024, 1024); using var gfx = Graphics.FromImage(bmp); using var brush = new SolidBrush(color); gfx.FillRectangle(brush, 0, 0, 1024, 1024); using var stream = new MemoryStream(); bmp.Save(stream, ImageFormat.Bmp); stream.Position = 0; var img = new BitmapImage(); img.BeginInit(); img.StreamSource = stream; img.CacheOption = BitmapCacheOption.OnLoad; img.EndInit(); img.Freeze(); return img; } }
视图代码
<Page x:Class="TestImgs.Views.MainPage" Style="{DynamicResource MahApps.Styles.Page}" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:properties="clr-namespace:TestImgs.Properties" xmlns:vms="clr-namespace:TestImgs.ViewModels" d:DataContext="{d:DesignInstance Type=vms:MainViewModel}" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="48" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <Button Grid.Row="0" Content="Render squares" Command="{Binding Path=RenderCmd}" /> <Grid Grid.Row="1" Background="{DynamicResource MahApps.Brushes.Gray10}"> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition /> <ColumnDefinition /> </Grid.ColumnDefinitions> <Image Grid.Column="0" Stretch="Fill" Source="{Binding Path=RedImg, Mode=OneWay}" /> <Image Grid.Column="1" Stretch="Fill" Source="{Binding Path=BlueImg, Mode=OneWay}" /> <Image Grid.Column="2" Stretch="Fill" Source="{Binding Path=GreenImg, Mode=OneWay}" /> </Grid> </Grid> </Page>
我的代码与网上类似解决方案一致,但仍无法正常显示。
问题修复方案
核心问题是未触发属性变更通知。虽然继承了ObservableObject,但直接使用自动属性赋值时,不会向WPF绑定系统发送属性值变化的信号,导致UI无法感知更新。
具体修复步骤
- 使用CommunityToolkit.Mvvm提供的
[ObservableProperty]特性,让框架自动生成带变更通知的属性; - 合并Dispatcher调用,减少UI线程调度开销。
修改后的ViewModel代码
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Windows; using System.Windows.Input; using System.Windows.Media.Imaging; using System.Windows.Threading; namespace TestImgs.ViewModels; public partial class MainViewModel : ObservableObject { [ObservableProperty] private BitmapImage redImg; [ObservableProperty] private BitmapImage blueImg; [ObservableProperty] private BitmapImage greenImg; public ICommand RenderCmd { get; set; } private readonly Dispatcher dispatcher; public MainViewModel() { dispatcher = Application.Current.Dispatcher; RenderCmd = new RelayCommand(Render); } public void Render() { dispatcher.Invoke(() => { RedImg = GetSolidImg(Color.Red); BlueImg = GetSolidImg(Color.Blue); GreenImg = GetSolidImg(Color.Green); }); } private static BitmapImage GetSolidImg(Color color) { var bmp = new Bitmap(1024, 1024); using var gfx = Graphics.FromImage(bmp); using var brush = new SolidBrush(color); gfx.FillRectangle(brush, 0, 0, 1024, 1024); using var stream = new MemoryStream(); bmp.Save(stream, ImageFormat.Bmp); stream.Position = 0; var img = new BitmapImage(); img.BeginInit(); img.StreamSource = stream; img.CacheOption = BitmapCacheOption.OnLoad; img.EndInit(); img.Freeze(); return img; } }
说明
[ObservableProperty]特性会自动生成包含SetProperty逻辑的公开属性,当属性值变化时自动触发PropertyChanged事件,WPF绑定系统会立即更新UI;- 把多个赋值操作放到同一个
dispatcher.Invoke调用中,避免多次线程切换,提升执行效率。
内容的提问来源于stack exchange,提问作者Miguel Pérez García
相关产品推荐
相关产品推荐

