gpt4 book ai didi

c# - 在 TabControl 的另一个选项卡中呈现内容控件

转载 作者:行者123 更新时间:2023-11-30 21:22:57 25 4
gpt4 key购买 nike

我有一个程序,其中有多个选项卡以编程方式动态添加到 TabControl 对象。我想要做的是将每个选项卡的内容值呈现为 PNG。我正在使用我在 StackOverflow 或 Google(丢失源代码)的其他地方获取的脚本。我的代码如下所示:

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{0.0, 0.0}。当我尝试将未查看选项卡的渲染大小强制为已查看选项卡之一时,我输出的 PNG 尺寸正确但完全为空。

所以我想我需要一些方法来强制呈现 TabContentControl。似乎 Render 事件只在需要呈现 UIElement 时才运行,因为它应该如此。我可以使用他们的任何技巧来解决这个问题吗?

我还尝试通过在创建选项卡时在 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 属性。当最后一行未被注释掉时,第一个选项卡处于焦点状态,具有相同的行为。其他标签没有任何渲染信息。

最佳答案

终于弄明白了,感谢this blog post .该解决方案涉及使用 Refresh 方法为 UIElement 创建一个扩展方法,该方法调用具有呈现优先级的空委托(delegate)。显然,安排具有渲染优先级的内容会导致执行所有其他更重要的项目,从而更改选项卡。

此处复制代码以防博客被删除:

public static class ExtensionMethods
{
private static Action EmptyDelegate = delegate() { };

public static void Refresh(this UIElement uiElement)
{
uiElement.Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate);
}
}

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;
tabItem.Refresh();
}
// tabPanel.SelectedIndex = 0;
}

要使用它,只需在您需要使用此功能的代码文件中包含扩展命名空间,它就会出现在方法列表中。

关于c# - 在 TabControl 的另一个选项卡中呈现内容控件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2032415/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com