类库中的ImageSource不显示

本文关键字:显示 ImageSource 类库 | 更新日期: 2023-09-27 18:19:12

我的应用链接到一个类库(.dll)。在类库项目中,有三张图片被放入Resources.resx中。需要在运行时选择一个图像并显示在按钮上。在搜索了一下之后,我选择使用转换器来帮助xaml:

中的绑定。
[ValueConversion(typeof(Side), typeof(ImageSource))]
public class SideToImageConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        Side side = (Side)value;
        switch (side)
        {
            case Side.Left:
                return ToWpfBitmap(Properties.Resources.LeftArmOnCart);
            case Side.Right:
                return ToWpfBitmap(Properties.Resources.RightArmOnCart);
            case Side.Both:
                return ToWpfBitmap(Properties.Resources.RightArmOnCart);
            default:
                throw new ArgumentException("Current configuration is invalid");
        }
    }
    private static BitmapSource ToWpfBitmap(Bitmap bitmap)
    {
        using (MemoryStream stream = new MemoryStream())
        {
            bitmap.Save(stream, ImageFormat.Png);
            stream.Position = 0;
            BitmapImage result = new BitmapImage();
            result.BeginInit();
            // According to MSDN, "The default OnDemand cache option retains access to the stream until the image is needed."
            // Force the bitmap to load right now so we can dispose the stream.
            result.CacheOption = BitmapCacheOption.OnLoad;
            result.StreamSource = stream;
            result.EndInit();
            result.Freeze();
            return result;
        }
    }
}

xaml代码看起来像

<Image Source="{Binding Side, Converter={StaticResource SideToImageConverter}}" .../>

不幸的是,图像不会在不抛出任何异常的情况下静默显示。调试到转换器代码中,ToWpfBitmap()中的位图参数看起来很好(宽度/高度值是正确的)。

顺便说一句,作为另一个试验,下面的代码工作得很好。

[ValueConversion(typeof(Side), typeof(ImageSource))]
public class SideToImageConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        Side side = (Side)value;
        switch (side)
        {
            case Side.Left:
                return LoadBitmap("LeftArmOnCart.png");
            case Side.Right:
                return LoadBitmap("RightArmOnCart.png");
            case Side.Both:
                return LoadBitmap("RightArmOnCart.png");
            default:
                throw new ArgumentException("Current configuration is invalid");
        }
    }
    private static BitmapSource LoadBitmap(string name)
    {
        BitmapImage result = new BitmapImage();
        result.BeginInit();
        string uri = "c:/.../Resources/Images/" + name;
        result.CacheOption = BitmapCacheOption.OnLoad;
        result.UriSource = new Uri(uri, UriKind.Absolute);
        result.EndInit();
        return result;
    }
}

但是,绝对路径是不需要的。那么,我错过什么了吗?

我理解通过释放三个映像文件使用相对路径是可行的。但是,是否有可能不释放三个文件,而只是类库dll?

谢谢!

类库中的ImageSource不显示

我想你可以阅读一些东西来帮助你解决你的问题。我将从WPF中的打包URI开始,这样您就可以理解如何使用URI来检查特定库的位置。由于这些图像位于另一个程序集的资源文件中,请阅读链接中的"引用资源程序集文件"。

我认为另一件值得提及的事情是两种方法之间的区别是你提供一个UriSource(底部)和一个你不(顶部)。看看Image.Source,当在XAML中使用时,它期望一个imageUri。有了这个提示,我们可以说它肯定可能与uri有关。

事实上,你的图像已经被保存为它们存在的库中的流,所以我们不需要做任何事情来创建一个新的位图或你正在做的任何事情,相反,我们可以简单地提供一个有效的包URI并返回一个字符串。

我认为这样的东西应该工作,提供库的名称是YourApp.Models,在子文件夹Resources'Images':

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
    Side side = (Side)value;
    switch (side)
    {
        case Side.Left:
            return "pack://application:,,,/YourApp.Models;component/Resources/Images/LeftArmOnCart.png";
        case Side.Right:
        case Side.Both:
            return "pack://application:,,,/YourApp.Models;component/Resources/Images/RightArmOnCart.png";
        default:
            throw new ArgumentException("Current configuration is invalid");
    }
}

注意:路径名对正/反斜杠、程序集名、组件名敏感。确保所有内容格式正确。

这被认为是绝对URI。相对URI将只是"/Resources/Images/LeftArmOnCart.png",只有当该文件路径存在于调用它的程序集中时才会起作用——这意味着它不会为您工作,因为您是从另一个程序集调用的。

希望这对你有帮助!

已经有一个InteropBitmap类可以用来将GDI位图转换为WPF ImageSource,尽管我发现它不能很好地处理alpha通道。这是我使用的机制:

public static BitmapSource CreateBitmapSourceFromGdiBitmap(Bitmap bitmap)
{
    if (bitmap == null)
        throw new ArgumentNullException("bitmap");
    var rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
    var bitmapData = bitmap.LockBits(
        rect,
        ImageLockMode.ReadWrite,
        PixelFormat.Format32bppArgb);
    try
    {
        var size = (rect.Width * rect.Height) * 4;
        return BitmapSource.Create(
            bitmap.Width,
            bitmap.Height,
            bitmap.HorizontalResolution,
            bitmap.VerticalResolution,
            PixelFormats.Bgra32,
            null,
            bitmapData.Scan0,
            size,
            bitmapData.Stride);
    }
    finally
    {
        bitmap.UnlockBits(bitmapData);
    }
}

请注意,此实现采用32bpp ARGB像素格式。如果你使用的是PNG图像,这应该没问题。否则,您需要添加一个转换步骤。