我正在将图像加载到背景中,我希望包含它的Silverlight画布全部调整为图像大小的图像大小(或我确定的最大值或最小值)。所以我做了以下事情:
private int ImageMargin = 4;
public Page()
{
InitializeComponent();
BitmapImage bi = new BitmapImage(new Uri("1.jpg", UriKind.Relative));
backgroundImage.Source = bi;
bi.DownloadProgress += new EventHandler<DownloadProgressEventArgs>(bi_DownloadProgress);
backgroundImage.SizeChanged += new SizeChangedEventHandler(backgroundImage_SizeChanged);
}
void bi_DownloadProgress(object sender, DownloadProgressEventArgs e)
{
if (e.Progress == 100)
{
LayoutRoot.Height = backgroundImage.Height + ImageMargin * 2;
LayoutRoot.Width = backgroundImage.Width + ImageMargin * 2;
}
}
图像加载正确,但无论我在哪里放置backgroundImage.Height / Width(关闭.Loaded事件,.SizeChanged事件[1],使用边框[2]等),它总是返回0.0或NaN的。我做错了什么?
[1] http://silverlight.net/forums/t/14855.aspx [2] http://silverlight.net/forums/t/90235.aspx
答案 0 :(得分:2)
private Image image;
public Page()
{
InitializeComponent();
LoadImage("image.png");
}
private void LoadImage(string path)
{
Uri uri = new Uri(path, UriKind.Relative);
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.UriSource = uri;
bitmapImage.DownloadProgress +=
new EventHandler<DownloadProgressEventArgs>(bitmapImage_DownloadProgress);
}
void bitmapImage_DownloadProgress(object sender, DownloadProgressEventArgs e)
{
if (e.Progress == 100)
{
Dispatcher.BeginInvoke(delegate()
{
double height = image.ActualHeight;
double width = image.ActualWidth;
});
}
}
KEY就是这一行:
致电 Dispatcher.BeginInvoke(delegate(){... });在获得之前需要 宽度/高度或它们可能是 间歇性地为零。
答案 1 :(得分:1)
您可能需要等待一个UI循环周期才能确保Silverlight有机会更新布局。此外,您必须确保图像实际可见。我实际上写了一个小例程,它从图像二进制文件中获取图像大小。下行是你必须通过WebClient明确下载图像,但好处是你会知道尺寸而不实际显示任何东西:
namespace StatMap.Silverlight.Services.UIHelpers
{
public static class ImageSizeExtractor
{
public static bool TryGetImageSize(byte[] buf, out int width, out int height)
{
return TryGetPngSize(buf, out width, out height) || TryGetJpegSize(buf, out width, out height);
}
private static bool IsPng(byte[] buf)
{
return (buf.Length > 8)&&(buf[0] == 137) && (buf[1] == 80) && (buf[2] == 78) && (buf[3] == 71)
&& (buf[4]==13)&&(buf[5]== 10)&&(buf[6]== 26)&&(buf[7]== 10);
}
private static bool TryGetPngSize(byte[] buf, out int width, out int height)
{
width = 0;
height = 0;
if (IsPng(buf))
{
int index = -1;
for (int i = 8; i < buf.Length - 12;i++)
{
if ((buf[i]==0x49)&&(buf[i+1]==0x48)&&(buf[i+2]==0x44)&&(buf[i+3]==0x52))
{
index = i + 4;
break;
}
}
if (index<0)
{
return false;
}
width = buf[index + 3] + buf[index + 2]*256;
height = buf[index + 7] + buf[index + 6]*256;
return true;
}
return false;
}
private static bool TryGetJpegSize(byte[] buf, out int width, out int height)
{
//static char get_jpeg_size(unsigned char* data, unsigned int data_size, unsigned short *width, unsigned short *height) {
//Check for valid JPEG image
int i = 0; // Keeps track of the position within the file
width = 0;
height = 0;
if (buf[i] == 0xFF && buf[i + 1] == 0xD8 && buf[i + 2] == 0xFF && buf[i + 3] == 0xE0)
{
i += 4;
// Check for valid JPEG header (null terminated JFIF)
if (buf[i + 2] == 'J' && buf[i + 3] == 'F' && buf[i + 4] == 'I' && buf[i + 5] == 'F' &&
buf[i + 6] == 0x00)
{
//Retrieve the block length of the first block since the first block will not contain the size of file
int blockLength = buf[i]*256 + buf[i + 1];
while (i < buf.Length)
{
i += blockLength; //Increase the file index to get to the next block
if (i >= buf.Length) return false; //Check to protect against segmentation faults
if (buf[i] != 0xFF) return false; //Check that we are truly at the start of another block
if (buf[i + 1] == 0xC0)
{
//0xFFC0 is the "Start of frame" marker which contains the file size
//The structure of the 0xFFC0 block is quite simple [0xFFC0][ushort length][uchar precision][ushort x][ushort y]
width = buf[i + 5]*256 + buf[i + 6];
height = buf[i + 7]*256 + buf[i + 8];
return true;
}
i += 2; //Skip the block marker
blockLength = buf[i]*256 + buf[i + 1]; //Go to the next block
}
return false; //If this point is reached then no size was found
}
return false;
}
return false;
}
}
}
希望这有帮助。