WinUI 3:动态加载的SVG图标无法正确渲染的原因
问题概述
在构建包含静态和动态菜单项的NavigationView时,静态菜单项通过URI加载SVG图标可正常显示,但动态通过流加载SVG图标的菜单项无法正确渲染图标。
静态XAML代码:
<NavigationViewItem Content="Static item"> <NavigationViewItem.Icon> <ImageIcon Source="/Assets/Android_Jelly_Bean_Logo.svg"/> </NavigationViewItem.Icon> </NavigationViewItem>
动态C#代码(原版本):
private async void _addNavigationItem() { var svgCode = "<my svg code string>"; var svgSource = new SvgImageSource(); var imageIcon = new ImageIcon(); imageIcon.Source = svgSource; var svgBuffer = CryptographicBuffer.ConvertStringToBinary(svgCode, BinaryStringEncoding.Utf8); using (var stream = svgBuffer.AsStream()) { await svgSource.SetSourceAsync(stream.AsRandomAccessStream()); } var item = new NavigationViewItem() { Content = "hello", Icon = imageIcon }; NavigationViewControl.MenuItems.Add(item); }
可能的原因及解决方法
1. SVG代码无效或不完整
原代码中svgCode为占位符,必须确保使用完整、有效的SVG内容。可通过HttpClient获取目标SVG的内容:
private async Task<string> GetSvgContentAsync() { using var client = new HttpClient(); return await client.GetStringAsync("https://upload.wikimedia.org/wikipedia/commons/7/7a/Android_Jelly_Bean_Logo.svg"); }
2. 流位置未重置
字符串转流后,流的默认位置处于末尾,导致SetSourceAsync无法读取内容。需在使用前重置流位置到开头:
using (var stream = svgBuffer.AsStream()) { stream.Position = 0; // 重置流位置 await svgSource.SetSourceAsync(stream.AsRandomAccessStream()); }
3. Async void方法的潜在问题
async void方法无法被正确等待,且异常会直接抛出到调用上下文,建议改为async Task并在调用时使用await:
private async Task AddNavigationItemAsync() { // 原逻辑... } // 调用示例 await AddNavigationItemAsync();
4. SVG尺寸未适配NavigationView图标大小
NavigationView图标有固定尺寸(通常为24x24),若SVG未设置width和height属性,可能导致渲染异常。可手动设置SvgImageSource的解码尺寸:
var svgSource = new SvgImageSource() { DecodePixelWidth = 24, DecodePixelHeight = 24 };
修正后的完整代码
private async Task AddNavigationItemAsync() { // 获取有效的SVG内容 using var client = new HttpClient(); var svgCode = await client.GetStringAsync("https://upload.wikimedia.org/wikipedia/commons/7/7a/Android_Jelly_Bean_Logo.svg"); var svgSource = new SvgImageSource() { DecodePixelWidth = 24, DecodePixelHeight = 24 }; var imageIcon = new ImageIcon(); imageIcon.Source = svgSource; var svgBuffer = CryptographicBuffer.ConvertStringToBinary(svgCode, BinaryStringEncoding.Utf8); using (var stream = svgBuffer.AsStream()) { stream.Position = 0; await svgSource.SetSourceAsync(stream.AsRandomAccessStream()); } var item = new NavigationViewItem() { Content = "hello", Icon = imageIcon }; NavigationViewControl.MenuItems.Add(item); }
内容的提问来源于stack exchange,提问作者Daniele Pugliese
相关产品推荐
相关产品推荐

