类库中的ImageSource不会显示

时间:2014-08-22 16:44:12

标签: c# wpf xaml

我的应用程序链接到类库(.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()中的位图参数看起来很好(宽度/高度值是正确的)。

BTW,作为另一个试验,以下代码工作正常。

[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?

谢谢!

2 个答案:

答案 0 :(得分:0)

我认为您可以阅读一些内容来帮助解决您的问题。我将从Pack URIs in WPF开始,以便您了解如何使用URI检查特定库的位置。由于这些图像位于另一个程序集的资源文件中,因此请阅读&#34;参考资源程序集文件&#34;在链接中。

我认为值得一提的另一件事是两种方法之间的区别在于你提供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",只有当该文件路径存在于调用它的程序集中时才会起作用 - 这意味着它不会为你工作,因为你从另一个程序集调用。 / p>

希望这有帮助!

答案 1 :(得分:0)

已经有一个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图像,那应该没问题。否则,您需要添加转换步骤。