[英]WPF: How to generate screenshots of items within a ItemsControl (within a TabView)
I have a TabControl where each tab is a user control that has an ItemsControl in it.我有一个 TabControl,其中每个选项卡都是一个用户控件,其中包含一个 ItemsControl。 The TabControl is bound to a collection and has an ItemTemplate:
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}"/>
Likewise, the ItemsControl in each tab is bound to data (complicated by a TemplateSelector).同样,每个选项卡中的 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>
I'd like to get a collection of collection of images for all the items (to use as scaled down images in another part of UI).我想获取所有项目的图像集合(在 UI 的另一部分用作按比例缩小的图像)。 I am having difficulty for two reasons: 1) trying to access the items of the TabControl/ItemsControl gives the dataitems not the visual items and 2) the visual elements of the TabControl are only created for the currently selected tab.
我遇到困难有两个原因:1) 尝试访问 TabControl/ItemsControl 的项目给出的是数据项而不是视觉项目,以及 2) TabControl 的视觉元素仅为当前选定的选项卡创建。
My thought was to capture each Tab when the Tab is selected and store this with something like:我的想法是在选择选项卡时捕获每个选项卡并将其存储为:
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);
}));
}
Is there a better way of doing this?有更好的方法吗?
And do I have to do the same thing with getting the visual children of the ItemsControl to get an image for each item?我是否必须做同样的事情来让 ItemsControl 的视觉子项为每个项目获取图像?
Here is some code that I have used in the past to generate pictures from controls/screen (I usually wrap the control I am trying to take a picture of in a grid/border for simplicity)这是我过去用来从控件/屏幕生成图片的一些代码(为简单起见,我通常将要拍摄的控件包装在网格/边框中)
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
}
Usage:用法:
byte[] bytes = ImageHelper.FrameworkElementToBitmap(mygrid, EncodingTypes.JPEG);
Xaml: Xaml:
<Grid x:Name="mygrid" Background="White">***controls you want to take pics of***</Grid>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.