我有ListView,它显示一些图片。并非所有图片都在屏幕上(在窗口中)可见。我想做一些类似“联系表”的东西 - 所有图片。
我从ListView中获取了ScrollViewer,并获取了它的完整高度(scrVwr.ExtentHeight)。所以,我调用渲染:
var bmp = new RenderTargetBitmap(scrVwr.Width, scrVwr.ExtentHeight, 96, 96, PixelFormats.Pbgra32);
bmp.Render(scrVwr);
保存后
var encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bmp));
var fileStream = IO.File.Create(picker.FileName);
encoder.Save(fileStream);
我得到了这个: 已保存JPG
(因此仅渲染 ListView.ActualHeight)
我想渲染整个 ListView/ScrollViewer (所有项目)。
我认为在你的情况下,你不应该尝试从渲染的 UI 创建图像。这引入了可避免的问题,例如 UI 虚拟化。
相反,我建议从
ListView
显示的原始图像源数据创建平铺图像。
以下示例使用
WriteableBitMap
动态创建平铺图像。
var uris = new List<Uri>
{
new Uri(@"C:\some_image.png", UriKind.Absolute),
new Uri(@"C:\some_image.png", UriKind.Absolute),
new Uri(@"C:\some_image.png", UriKind.Absolute),
};
int minTilePixelWidth = 1000;
int tileRowPixelHeight = 200;
var tileImageCreator = new TileImageCreator();
BitmapSource imageSource = tileImageCreator.CreateTileImage(uris, minTilePixelWidth, tileRowPixelHeight);
SaveToFile(imageSource);
Tile.cs
internal readonly struct Tile
{
public Tile(BitmapImage image, int horizontalOffset, int verticalOffset)
{
this.Image = image;
this.HorizontalOffset = horizontalOffset;
this.VerticalOffset = verticalOffset;
}
public int HorizontalOffset { get; }
public BitmapImage Image { get; }
public int VerticalOffset { get; }
}
TileImageCreator.cs
class TileImageCreator
{
public BitmapSource CreateTileImage(IEnumerable<Uri> imageUris, int minTilePixelWidth, int tileRowPixelHeight)
{
int tileHeight = tileRowPixelHeight;
int tileWidth = minTilePixelWidth;
int horizontalOffset = 0;
int verticalOffset = 0;
var tileInfos = new List<Tile>();
foreach (Uri uri in imageUris)
{
var image = new BitmapImage();
image.BeginInit();
image.UriSource = uri;
image.DecodePixelHeight = tileRowPixelHeight;
image.EndInit();
image.Freeze();
tileWidth = Math.Max(tileWidth, image.PixelWidth);
int newRowWidth = horizontalOffset + image.PixelWidth;
bool isOverflowing = newRowWidth > tileWidth;
if (isOverflowing)
{
horizontalOffset = 0;
verticalOffset += tileRowPixelHeight;
tileHeight += tileRowPixelHeight;
}
var tileInfo = new Tile(image, horizontalOffset, verticalOffset);
tileInfos.Add(tileInfo);
horizontalOffset += image.PixelWidth;
}
var tileBitmap = new WriteableBitmap(tileWidth, tileHeight, 96, 96, PixelFormats.Pbgra32, null);
foreach (Tile tile in tileInfos)
{
BitmapImage tileImage = tile.Image;
int bytesPerPixel = (tileImage.Format.BitsPerPixel + 7) / 8;
int stride = tileImage.PixelWidth * bytesPerPixel;
int bufferSize = tileImage.PixelHeight * stride;
byte[] sourceBuffer = new byte[bufferSize];
tileImage.CopyPixels(sourceBuffer, stride, 0);
tileBitmap.WritePixels(new Int32Rect(0, 0, tileImage.PixelWidth, tileImage.PixelHeight), sourceBuffer, stride, tile.HorizontalOffset, tile.VerticalOffset);
}
tileBitmap.Freeze();
return tileBitmap;
}
}