如何在.NET MAUI XAML中加载外部(非嵌入式)图像?

wtlkbnrh  于 2023-09-28  发布在  .NET
关注(0)|答案(1)|浏览(165)

我有一个问题,弄清楚如何加载图像在XAML的图像文件不是嵌入在应用程序本身。我不能使用C#,因为XAML文件是在运行时动态加载和解析的。所以你不能挂接一个方法或事件来从C#加载图像源。它必须在XAML中完成。
一旦我的应用程序启动,它就会从Web服务器下载最新的资源:

private static void DownloadResourcesFromWebServer(string url)
{
    try
    {
        string finalPath = Path.Combine(Microsoft.Maui.Storage.FileSystem.AppDataDirectory, "resources_tmp.zip");
        if (File.Exists(finalPath))
        {
              File.Delete(finalPath);
        }

        using HttpClient client = new HttpClient();
        using HttpResponseMessage response = client.GetAsync(url).Result;
        using HttpContent content = response.Content;
        using Stream stream = content.ReadAsStreamAsync().Result;
        using FileStream fs = new FileStream(finalPath, FileMode.OpenOrCreate, FileAccess.Write);

        stream.CopyTo(fs);
        fs.Flush();
        fs.Close();

        ZipFile.ExtractToDirectory(finalPath, Microsoft.Maui.Storage.FileSystem.AppDataDirectory);
    } catch(Exception ex)
    {
        Logger.Log(ex);
        Debugger.Break();
    }
}

如您所见,我的所有资源都导出到Microsoft.Maui.Storage.FileSystem.AppDataDirectory路径。
但我似乎不能让这个工作。我无法定义要从此路径加载的图像的源。
我是不是漏了什么?我是否使用了错误的路径来保存我的资源(在这种情况下仅限图像)?
我尝试在XAML文件中使用测试<Image>标记访问下载的图像。我尝试了以下配置(都没有成功)

<Image Source="files/NAME.png" />
<Image Source="NAME.png" />
<Image>
    <Image.Source>
        <FileImageSource File="files/NAME.png"></FileImageSource>
    </Image.Source>
</Image>

<Image>
    <Image.Source>
        <FileImageSource File="NAME.png"></FileImageSource>
    </Image.Source>
</Image>

PS:该项目是不是一个Blazor应用程序

u4vypkhs

u4vypkhs1#

回答我自己的问题:
我听从了Jason的建议,通过数据绑定来实现。
要动态获取正确的资源路径(在iOS和Android上会有所不同),您只需使用自定义的ValueConverter。
要做到这一点,你首先需要将它定义为这样的类:

public class FrameworkPathConverter : IValueConverter
{
    /// <summary>
    /// Converts a path to a full qualified, platform specific path.
    /// </summary>
    /// <param name="parameter">The path of the file to be qualified</param>
    /// <returns></returns>
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (parameter is string fileName)
        {
            return Path.Combine(Microsoft.Maui.Storage.FileSystem.AppDataDirectory, fileName);
        }
        return value;
    }
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => throw new NotImplementedException();
}

然后,您需要在应用程序中全局注册它(参考资料),如下所示:

?xml version="1.0" encoding="utf-8" ?>
<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="AppFramework.App"
             xmlns:conv="clr-namespace:AppFramework.Converter">
             
    <Application.Resources>
        <ResourceDictionary>
            <!-- ... -->

            <!-- Custom Converter -->
            <conv:FrameworkPathConverter x:Key="FrameworkPathConverter" />
            
            <!-- ... -->
        </ResourceDictionary>
    </Application.Resources>
</Application>

您可能需要更改xmlns:conv="clr-namespace:AppFramework.Converter"以匹配您的名称空间,并更改<conv:FrameworkPathConverter x:Key="FrameworkPathConverter" />以匹配您的类名。
然后,您可以使用它来显示下载和提取的图像,如下所示:

<Image Source="{Binding Converter={StaticResource FrameworkPathConverter}, ConverterParameter=logo_wide.jpg}"></Image>

您只需将创建的转换器传递给Converter(作为静态资源),并使用要转换为完整路径的文件的名称作为“ConverterParameter”。
通过对FrameworkPathConverter类中的Convert()方法进行一些修改,您可以根据需要使用不同的路径。
我不确定这是否是最优、最有效和最方便的方法,但目前它正按预期工作。
我仍然很乐意得到其他可以解决这个问题的答案。

相关问题