如何以编程方式将非常宽的 GridView 转换为位图图像?
How can I programmatically convert a very wide GridView to a bitmap image?
如何以编程方式将非常宽的 GridView 转换为位图图像?我需要所有数据显示在一张位图图像中。
Xaml:
<StackPanel>
<telerik:RadGridView x:Name="GridView1" ItemsSource="{Binding MyProperties1}" AutoGenerateColumns="True" />
<telerik:RadGridView x:Name="GridView2" ItemsSource="{Binding MyProperties2}" AutoGenerateColumns="True" />
</StackPanel>
在Windows表单中使用DrawToBitmap
很方便,可以为所欲为。在 WPF 中,您可以使用 RenderTargetBitmap
、BitmapFrame
和 BmpBitmapEncoder
来做到这一点。
void SaveToBmp(FrameworkElement control, string fileName)
{
var bmpEncoder = new BmpBitmapEncoder();
SaveControlToImage(control, fileName, bmpEncoder);
}
void SaveControlToImage(FrameworkElement control, string fileName, BitmapEncoder encoder)
{
// Keep the current postion relative to the container
UIElement container = VisualTreeHelper.GetParent(control) as UIElement;
Point curPos = control.TranslatePoint(new Point(0.0, 0.0), container);
RenderTargetBitmap bitmap = new RenderTargetBitmap((int)control.ActualWidth, (int)control.ActualHeight, 96, 96, PixelFormats.Pbgra32);
Size visualSize = new Size(control.ActualWidth, control.ActualHeight);
control.Measure(visualSize);
control.Arrange(new Rect(visualSize));
bitmap.Render(control);
BitmapFrame frame = BitmapFrame.Create(bitmap);
encoder.Frames.Add(frame);
using (var stream = File.Create(fileName))
{
encoder.Save(stream);
}
control.Arrange(new Rect(curPos, visualSize));
}
并使用以下代码将您的 GridView 保存到图像文件:
SaveToBmp(GridView1, @"D:\gridview1.bmp");
参考Easiest way of saving wpf Image control to a file并添加一些改进。
@Yanger Yang's is close, but you should use the element's DesiredSize
instead of its ActualWidth
/ActualHeight
。当然,这是假设您没有在 Grid
元素本身上设置明确的大小。这种方法应该适用于您的 telerik:RadGridView
,但我没有可用于测试的库。
这是一个示例项目,其中包含 Grid
,ScrollViewer
内有十五 (15) 列。
<Window x:Class="PrintableGridDemo.MainWindow"
Title="Printable Grid" Height="600" Width="800">
<DockPanel>
<Button DockPanel.Dock="Top"
HorizontalAlignment="Right"
Margin="0 10 10 0"
Padding="50 10"
Content="Print"
Click="PrintButton_Click"/>
<Border Margin="10"
BorderBrush="DarkGray"
BorderThickness="1">
<ScrollViewer HorizontalScrollBarVisibility="Visible"
VerticalScrollBarVisibility="Visible">
<Grid x:Name="MyGrid"
Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
</Grid>
</ScrollViewer>
</Border>
</DockPanel>
</Window>
我已经 (ab) 使用 class 的构造函数用包含列号的示例数据填充 Grid
,这样您就可以看到生成的图像包含网格.
public MainWindow()
{
InitializeComponent();
for (int col = 0; col < MyGrid.ColumnDefinitions.Count; col++)
{
var control = new TextBlock() {
Text = $"This is column number { col + 1 }. It is a column with almost no dynamic data. The only dynamic data is the number corresponding to this column's index in the grid plus one since users prefer one-indexed values while the framework uses zero-indexed values.",
TextWrapping = TextWrapping.Wrap
};
MyGrid.Children.Add(control);
Grid.SetColumn(control, col);
}
}
这是项目 运行 完成时的样子。
这是单击“打印”按钮的结果。如您所见,使用网格的 DesiredSize
允许我们查看所有列的内容(并且还删除了网格扩展以填充 ScrollViewer
的额外布局空白)。
点击“打印”按钮后会发生以下情况:
private void PrintButton_Click(object sender, RoutedEventArgs e)
{
// Set up the output file.
string destination = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
string fileName = $"GridImage_{DateTime.Now:yyyy-MMM-dd_hh-mm-ss-tt}.png";
string filePath = Path.Combine(destination, fileName);
// Render the control as a Bitmap.
RenderTargetBitmap image = new((int)MyGrid.DesiredSize.Width, (int)MyGrid.DesiredSize.Height, 96, 96, PixelFormats.Pbgra32);
image.Render(MyGrid);
// Encode the Bitmap image as a PNG instead.
PngBitmapEncoder encoder = new();
encoder.Frames.Add(BitmapFrame.Create(image));
// Save the PNG to the file.
using FileStream stream = File.Create(filePath);
encoder.Save(stream);
}
关键点在这里:
RenderTargetBitmap image = new(
// The key bit.
(int)MyGrid.DesiredSize.Width,
(int)MyGrid.DesiredSize.Height,
// Format specific parameters. You can ignore these.
96, 96, PixelFormats.Pbgra32);
因为我们使用的是元素的 DesiredSize
,渲染将包含通常不会渲染的元素部分(因为它们在 UI 中不可见)。
如果您 运行 遇到裁剪问题,您可以调用元素的 Measure
方法来重新计算元素的当前 DesiredSize
.
如何以编程方式将非常宽的 GridView 转换为位图图像?我需要所有数据显示在一张位图图像中。
Xaml:
<StackPanel>
<telerik:RadGridView x:Name="GridView1" ItemsSource="{Binding MyProperties1}" AutoGenerateColumns="True" />
<telerik:RadGridView x:Name="GridView2" ItemsSource="{Binding MyProperties2}" AutoGenerateColumns="True" />
</StackPanel>
在Windows表单中使用DrawToBitmap
很方便,可以为所欲为。在 WPF 中,您可以使用 RenderTargetBitmap
、BitmapFrame
和 BmpBitmapEncoder
来做到这一点。
void SaveToBmp(FrameworkElement control, string fileName)
{
var bmpEncoder = new BmpBitmapEncoder();
SaveControlToImage(control, fileName, bmpEncoder);
}
void SaveControlToImage(FrameworkElement control, string fileName, BitmapEncoder encoder)
{
// Keep the current postion relative to the container
UIElement container = VisualTreeHelper.GetParent(control) as UIElement;
Point curPos = control.TranslatePoint(new Point(0.0, 0.0), container);
RenderTargetBitmap bitmap = new RenderTargetBitmap((int)control.ActualWidth, (int)control.ActualHeight, 96, 96, PixelFormats.Pbgra32);
Size visualSize = new Size(control.ActualWidth, control.ActualHeight);
control.Measure(visualSize);
control.Arrange(new Rect(visualSize));
bitmap.Render(control);
BitmapFrame frame = BitmapFrame.Create(bitmap);
encoder.Frames.Add(frame);
using (var stream = File.Create(fileName))
{
encoder.Save(stream);
}
control.Arrange(new Rect(curPos, visualSize));
}
并使用以下代码将您的 GridView 保存到图像文件:
SaveToBmp(GridView1, @"D:\gridview1.bmp");
参考Easiest way of saving wpf Image control to a file并添加一些改进。
@Yanger Yang's DesiredSize
instead of its ActualWidth
/ActualHeight
。当然,这是假设您没有在 Grid
元素本身上设置明确的大小。这种方法应该适用于您的 telerik:RadGridView
,但我没有可用于测试的库。
这是一个示例项目,其中包含 Grid
,ScrollViewer
内有十五 (15) 列。
<Window x:Class="PrintableGridDemo.MainWindow"
Title="Printable Grid" Height="600" Width="800">
<DockPanel>
<Button DockPanel.Dock="Top"
HorizontalAlignment="Right"
Margin="0 10 10 0"
Padding="50 10"
Content="Print"
Click="PrintButton_Click"/>
<Border Margin="10"
BorderBrush="DarkGray"
BorderThickness="1">
<ScrollViewer HorizontalScrollBarVisibility="Visible"
VerticalScrollBarVisibility="Visible">
<Grid x:Name="MyGrid"
Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
</Grid>
</ScrollViewer>
</Border>
</DockPanel>
</Window>
我已经 (ab) 使用 class 的构造函数用包含列号的示例数据填充 Grid
,这样您就可以看到生成的图像包含网格.
public MainWindow()
{
InitializeComponent();
for (int col = 0; col < MyGrid.ColumnDefinitions.Count; col++)
{
var control = new TextBlock() {
Text = $"This is column number { col + 1 }. It is a column with almost no dynamic data. The only dynamic data is the number corresponding to this column's index in the grid plus one since users prefer one-indexed values while the framework uses zero-indexed values.",
TextWrapping = TextWrapping.Wrap
};
MyGrid.Children.Add(control);
Grid.SetColumn(control, col);
}
}
这是项目 运行 完成时的样子。
这是单击“打印”按钮的结果。如您所见,使用网格的 DesiredSize
允许我们查看所有列的内容(并且还删除了网格扩展以填充 ScrollViewer
的额外布局空白)。
点击“打印”按钮后会发生以下情况:
private void PrintButton_Click(object sender, RoutedEventArgs e)
{
// Set up the output file.
string destination = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
string fileName = $"GridImage_{DateTime.Now:yyyy-MMM-dd_hh-mm-ss-tt}.png";
string filePath = Path.Combine(destination, fileName);
// Render the control as a Bitmap.
RenderTargetBitmap image = new((int)MyGrid.DesiredSize.Width, (int)MyGrid.DesiredSize.Height, 96, 96, PixelFormats.Pbgra32);
image.Render(MyGrid);
// Encode the Bitmap image as a PNG instead.
PngBitmapEncoder encoder = new();
encoder.Frames.Add(BitmapFrame.Create(image));
// Save the PNG to the file.
using FileStream stream = File.Create(filePath);
encoder.Save(stream);
}
关键点在这里:
RenderTargetBitmap image = new(
// The key bit.
(int)MyGrid.DesiredSize.Width,
(int)MyGrid.DesiredSize.Height,
// Format specific parameters. You can ignore these.
96, 96, PixelFormats.Pbgra32);
因为我们使用的是元素的 DesiredSize
,渲染将包含通常不会渲染的元素部分(因为它们在 UI 中不可见)。
如果您 运行 遇到裁剪问题,您可以调用元素的 Measure
方法来重新计算元素的当前 DesiredSize
.