[英]WPF: How to generate screenshots of items within a ItemsControl (within a TabView)
我有一個 TabControl,其中每個選項卡都是一個用戶控件,其中包含一個 ItemsControl。 TabControl 綁定到一個集合並有一個 ItemTemplate:
<DataTemplate x:Key="tabContentTemplate">
<tabs:VisualizationTab x:Name="VisualizationTab"/>
</DataTemplate>
<TabControl x:Name="tabControl" SelectionChanged="tabControl_SelectionChanged"
ItemsSource="{Binding TabViewModels, Mode=TwoWay}" ItemHeaderTemplate="{StaticResource tabHeaderTemplate}"
ItemTemplate="{StaticResource tabContentTemplate}"/>
同樣,每個選項卡中的 ItemsControl 都綁定到數據(由 TemplateSelector 復雜化)。
<UserControl.Resources>
<DataTemplate x:Key="classOneTemplate">
<charts:PlotOne DataContext="{Binding Converter={StaticResource plotOneViewModelConverter}}" />
</DataTemplate>
<DataTemplate x:Key="classTwoTemplate">
<charts:PlotTwo DataContext="{Binding Converter={StaticResource plotTwoViewModelConverter}}" />
</DataTemplate>
<local:VisualizationTemplateSelector ClassOneTemplate="{StaticResource classOneTemplate}" ClassTwoTemplate="{StaticResource classTwoTemplate}"
x:Key="visualizationTemplateSelector" />
</UserControl.Resources>
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<ItemsControl x:Name="visualizationItemsControl" ItemsSource="{Binding Path=VisualizationSpecs}" ItemTemplateSelector="{StaticResource visualizationTemplateSelector}">
<!-- ItemsPanelTemplate -->
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="{ Binding Path=ColumnCount}" Rows="{ Binding Path=RowCount}" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Grid>
我想獲取所有項目的圖像集合(在 UI 的另一部分用作按比例縮小的圖像)。 我遇到困難有兩個原因:1) 嘗試訪問 TabControl/ItemsControl 的項目給出的是數據項而不是視覺項目,以及 2) TabControl 的視覺元素僅為當前選定的選項卡創建。
我的想法是在選擇選項卡時捕獲每個選項卡並將其存儲為:
private void tabControl_SelectionChanged(object sender, TabControlSelectionChangedEventArgs e)
{
WorkspaceViewModel workspaceViewModel = tabControl.SelectedItem as WorkspaceViewModel;
if (workspaceViewModel is null)
return;
tabControl.Dispatcher.BeginInvoke(new Action(() =>
{
VisualizationTab visualizationTab = FindVisualChild<VisualizationTab>(tabControl);
workspaceViewModel.SetVisualizationTab(visualizationTab);
}));
}
有更好的方法嗎?
我是否必須做同樣的事情來讓 ItemsControl 的視覺子項為每個項目獲取圖像?
這是我過去用來從控件/屏幕生成圖片的一些代碼(為簡單起見,我通常將要拍攝的控件包裝在網格/邊框中)
using System.IO;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
public enum EncodingTypes : int
{
BMP,
GIF,
JPEG,
PNG,
TIFF,
WMP
}
public static class ImageHelper
{
#region " FrameworkElementToBitmap "
/// <summary>
/// FrameworkElementToBitmap
/// During signature capture, boundary does not get calculated correctly when user draws off the canvas.
/// Use a hidden border to determine the canvas boundary when capturing signature.
/// </summary>
/// <param name="border"></param>
/// <returns>byte[]</returns>
public static byte[] FrameworkElementToBitmap(UIElement border, EncodingTypes encType, double scale = 1.0)
{
byte[] bitmapBytes;
int width = (int)(border.RenderSize.Width * scale);
int height = (int)(border.RenderSize.Height * scale);
BitmapEncoder encoder;
switch (encType)
{
case EncodingTypes.GIF:
encoder = new GifBitmapEncoder();
break;
case EncodingTypes.JPEG:
encoder = new JpegBitmapEncoder();
break;
case EncodingTypes.PNG:
encoder = new PngBitmapEncoder();
break;
case EncodingTypes.TIFF:
encoder = new TiffBitmapEncoder();
break;
case EncodingTypes.WMP:
encoder = new WmpBitmapEncoder();
break;
default:
case EncodingTypes.BMP:
encoder = new BmpBitmapEncoder();
break;
}
//render ink to bitmap
RenderTargetBitmap renderBitmap = new RenderTargetBitmap(width, height, 96d, 96d, PixelFormats.Default);
Rect bounds = VisualTreeHelper.GetDescendantBounds(border);
//Use DrawingVisual to prevent having to move the control to the top of the screen to grab the bitmap
DrawingVisual dv = new DrawingVisual();
using (DrawingContext ctx = dv.RenderOpen())
{
ctx.PushTransform(new ScaleTransform(scale, scale));
ctx.DrawRectangle(
new VisualBrush(border),
null,
new Rect(new Point(), bounds.Size)); //new Rect(border.RenderSize));
}
renderBitmap.Render(dv);
//save the ink to a memory stream
encoder.Frames.Add(BitmapFrame.Create(renderBitmap));
using (MemoryStream ms = new MemoryStream())
{
encoder.Save(ms);
//get the bitmap bytes from the memory stream
bitmapBytes = ms.ToArray();
//Uncomment to save images when debugging
//#if DEBUG
// string savePath = Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData);
// string testFileName = Path.Combine(savePath, string.Format("{0}.{1}", DateTime.Now.ToString("yyyyMMdd_hhmmss"), encType.ToString().ToLower()));
// File.WriteAllBytes(testFileName, bitmapBytes);
//#endif
}
return bitmapBytes;
}
#endregion
}
用法:
byte[] bytes = ImageHelper.FrameworkElementToBitmap(mygrid, EncodingTypes.JPEG);
Xaml:
<Grid x:Name="mygrid" Background="White">***controls you want to take pics of***</Grid>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.