我有一个程序,其中有多个选项卡以TabControl
编程方式动态添加到对象中。我想要做的是将每个选项卡的 Content 值呈现为 PNG。我正在使用我在 StackOverflow 或谷歌的其他地方找到的脚本(丢失了源代码)。我的代码如下所示:
if (tabPanel.Items.Count > 0)
{
SaveFileDialog fileDialog = new SaveFileDialog();
fileDialog.Filter = "PNG|*.png";
fileDialog.Title = "Save Tabs";
fileDialog.ShowDialog();
if (fileDialog.FileName.Trim().Length > 0)
{
try
{
string filePrefix = fileDialog.FileName.Replace(".png", "");
int tabNo = 1;
foreach (TabItem tabItem in tabPanel.Items)
{
string filename = filePrefix + "_" + tabNo + ".png";
TabContentControl content = tabItem.Content as TabContentControl;
Rect rect = new Rect(content.RenderSize);
RenderTargetBitmap rtb = new RenderTargetBitmap((int)rect.Right, (int)rect.Bottom, 96d, 96d, System.Windows.Media.PixelFormats.Default);
rtb.Render(content);
BitmapEncoder pngEncoder = new PngBitmapEncoder();
pngEncoder.Frames.Add(BitmapFrame.Create(rtb));
System.IO.MemoryStream ms = new System.IO.MemoryStream();
pngEncoder.Save(ms);
System.IO.File.WriteAllBytes(filename, ms.ToArray());
ms.Close();
tabNo++;
}
}
catch (Exception ex)
{
// log exception
}
}
}
如果我在调用此代码之前浏览并查看了所有必须呈现的选项卡,则此代码可以正常工作。它继续并使用从 TabContentControl 呈现的正确内容创建 filePrefix_1.png、filePrefix_2.png 等。new RenderTargetBitmap(...)
但是,如果我在查看所有选项卡之前调用使用此代码的处理程序,我的代码会在因为content.RenderSize
is引发异常{0.0, 0.0}
。当我尝试将未查看选项卡的渲染大小强制为查看过的选项卡之一时,我输出的 PNG 尺寸正确,但完全为空。
所以我想我需要一些方法来强制呈现 TabContentControl。似乎只有在需要渲染 UIElement 时才运行 Render 事件。他们有什么诡计可以让我解决这个问题吗?
我还尝试通过在创建选项卡时在 Page_Loaded 事件处理程序中添加以下代码来“欺骗”WPF 来绘制选项卡内容:
void Page_Loaded(object sender, RoutedEventArgs e)
{
// irrelevant code
foreach (// iterate over content that is added to each tab)
{
TabItem tabItem = new TabItem();
// load content
tabPanel.Items.Add(tabItem);
tabItem.IsSelected = true;
}
// tabPanel.SelectedIndex = 0;
}
当Page_Loaded
处理程序中的最后一行被注释掉时,最后一个选项卡成为焦点并RenderSize
为其内容定义了属性。当最后一行没有被注释掉时,第一个标签是焦点,具有相同的行为。其他选项卡没有任何渲染信息。