我的方案如下。我正在为我的儿子创建一个小数学测验应用程序,并希望在每个问题得到解答后动态更改我的画布的背景ImageBrush。我继续将我的图像(pngs)嵌入到资源文件中,并想到我会将它们加载到一个数组中,然后随机选择一个并将其加载到画布中。
我遇到的第一个问题当然是资源文件中的图像被存储为位图。所以在浏览一下互联网后,我终于想出了如何使用以下帮助方法将它们从Bitmap转换为BitmapImage对象:
private BitmapImage FromResourceBitmap(Bitmap bitmap)
{
var result = new BitmapImage();
using(var stream = new MemoryStream())
{
bitmap.Save(stream, ImageFormat.Png);
stream.Position = 0;
result.BeginInit();
result.StreamSource = stream;
result.EndInit();
}
return result;
}
从那里我从BitmapImage创建了一个ImageBrush并将其分配给画布的Background属性:
var brush = new ImageBrush {ImageSource = m_Media.Screens[0]}; // m_Media.Screens[x] returns a BitmapImage...obviously.
QuestionCanvas.Background = brush;
不幸的是,这似乎不起作用。当应用程序运行时,背景是纯白色。我的XAML没有描述任何背景......我很困惑。任何帮助将不胜感激!谢谢!
答案 0 :(得分:1)
我想知道你的画布是否透明,或者你的画布上还有另一个元素。我会看看Codeplex上的Snoop来查看你的可视化树,并确切地确定发生了什么。当您转到下一个问题时,还可以考虑使用触发器或代码绑定为您设置图像。然后,您可以使用触发器将背景绑定到模板,或者将项目绑定到图像并让它自动更新。
答案 1 :(得分:0)
通过各种图像刷相关的类,特别是BitmapImage的寻找后,我开始觉得StreamSource的财产被简单地引用流代替的BitmapImage对象中建立一个本地副本。因此,我的帮助器方法中的using语句实际上释放了流,因此使BitmapImage的StreamSource为null。画布然后回落到纯白色(#FFFFFFFF)的SolidColorBrush(感谢詹姆斯提醒我的Snoop)。
所以,为了解决这个问题,我改为创建了一个私有List来保存对各种图像流的引用,然后将我的BitmapImages指向那些引用。当GC出现时,我实现了IDisposable来释放各种MemoryStream。这是缩写代码:
public class Media : IDisposable
{
private readonly List<BitmapImage> m_Screens = new List<BitmapImage>();
private readonly List<MemoryStream> m_BackingStreams = new List<MemoryStream>();
public BitmapImage MainScreen { get; private set; }
public List<BitmapImage> Screens
{
get
{
return m_Screens;
}
}
public Media()
{
LoadScreens();
}
private void LoadScreens()
{
m_BackingStreams.Add(FromResourceBitmap(Properties.Resources.Screen_01));
m_BackingStreams.Add(FromResourceBitmap(Properties.Resources.Screen_02));
m_BackingStreams.Add(FromResourceBitmap(Properties.Resources.Screen_03));
m_BackingStreams.Add(FromResourceBitmap(Properties.Resources.Screen_04));
m_BackingStreams.Add(FromResourceBitmap(Properties.Resources.Screen_05));
foreach (var stream in m_BackingStreams)
{
m_Screens.Add(FromResourceStream(stream));
}
}
private BitmapImage FromResourceStream(Stream stream)
{
var result = new BitmapImage();
result.BeginInit();
result.StreamSource = stream;
result.EndInit();
return result;
}
private MemoryStream FromResourceBitmap(Bitmap bitmap)
{
var stream = new MemoryStream();
bitmap.Save(stream, ImageFormat.Png);
return stream;
}
public void Dispose()
{
if (m_BackingStreams.Count == 0 || m_BackingStreams == null) return;
foreach (var stream in m_BackingStreams)
{
stream.Close();
stream.Flush();
}
}
以下是我在运行时实际设置Canvas的背景时的样子:
MainMenuCanvas.Background = new ImageBrush(m_Media.Screens[0]);
修复它,尽管它不够优雅。
在研究时,我确实在MSDN上的BitmapImage.StreamSource文档页面中遇到了一些信息:
将CacheOption属性设置为 BitmapCacheOption.OnLoad如果你愿意的话 之后关闭流 BitmapImage已创建。默认 OnDemand缓存选项保留访问权限 直到位图为止的流 需要,清理由。处理 垃圾收集器。
然而,当我试图用原始溶液与CacheOption枚举set到BitmapCacheOption.OnLoad它导致同样的问题。我可能在这里遗漏了一些东西,但是我想这显而易见的并不是那么明显。 :)