我想将每个图表从网格导出到系统中的图像文件。 下面是xaml和c#的代码。 问题是,如果我导出,只有第一张图表正在正确导出,但第二张图表没有得到导出,它没有映射到第二张图表导出。 下面是截屏。
XAML:
<TabItem x:Name="Charts" Header="Company Charts " TabIndex="0" IsSelected="True">
<ScrollViewer ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Auto" Background="Transparent" telerik:StyleManager.Theme="Expression_Dark">
<Grid>
<Grid x:Name="ChartGrid" Margin="10" Background="Black">
<Grid.Resources>
<telerik:RadContextMenu x:Key="context" Width="100" telerik:StyleManager.Theme="Expression_Dark">
<telerik:RadContextMenu.Background>
<LinearGradientBrush EndPoint="0.5,1" MappingMode="RelativeToBoundingBox" StartPoint="0.5,0">
<GradientStop Color="#FF515151" Offset="0.021"/>
<GradientStop Color="#FF212020" Offset="0.979"/>
<GradientStop Color="#FF222121" Offset="0.115"/>
</LinearGradientBrush>
</telerik:RadContextMenu.Background>
<telerik:RadMenuItem Header="View Data" Foreground="White" Command="{Binding ViewData}" CommandParameter="{Binding RelativeSource={RelativeSource Self}}" telerik:StyleManager.Theme="Expression_Dark"></telerik:RadMenuItem>
<telerik:RadMenuItem Header="Edit Chart" Foreground="White" Command="{Binding EditChartCmd}" CommandParameter="{Binding RelativeSource={RelativeSource Self}}" telerik:StyleManager.Theme="Expression_Dark"></telerik:RadMenuItem>
</telerik:RadContextMenu>
<DataTemplate x:Key="EmptyContentTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="N.A." Margin="5,15,0,0" VerticalAlignment="Center" Height="30" Foreground="{Binding LabelFG}"></TextBlock>
</StackPanel>
</DataTemplate>
<!--<DataTemplate x:Key="LegendOrientation">
<StackPanel Orientation="Horizontal" />
</DataTemplate>-->
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
</Grid>
</Grid>
</ScrollViewer>
</TabItem>
C#CODE:
private void ExportCHARTtoBMP(RadCartesianChart chartx, string p)
{
chartx.Measure(new System.Windows.Size(double.PositiveInfinity, double.PositiveInfinity));
int chartW = (int)Math.Round(chartx.ActualWidth);
int chartH = (int)Math.Round(chartx.ActualHeight);
chartW = chartW == 0 ? 1 : chartW;
chartH = chartH == 0 ? 1 : chartH;
RenderTargetBitmap rtbmp = new RenderTargetBitmap(chartW + 32, chartH + 20, 96d, 96d, PixelFormats.Default);
rtbmp.Render(chartx);
BmpBitmapEncoder encoder = new BmpBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(rtbmp));
FileStream chartFS = File.Create(tempPath + "" + p + ".bmp");
encoder.Save(chartFS);
chartFS.Close();
rtbmp.Clear();
}
private void charttoimageprocess(List<string> axisdata1, List<string> axisdata2)
{
for (int row = 0; row < (chartgridimage.RowDefinitions.Count()); row++)
{
for (int column = 0; column < chartgridimage.ColumnDefinitions.Count(); column++)
{
RadCartesianChart chart = chartgridimage.ChildrenOfType<RadCartesianChart>().FirstOrDefault(e => Grid.GetRow(e) == row && Grid.GetColumn(e) == column);
chart.UpdateLayout();
chart.Arrange(new Rect(new System.Windows.Size(chart.ActualWidth, chart.ActualHeight)));
chart.UpdateLayout();
ExportCHARTtoBMP(chart, "chart" + row + "" + column);
chart_names.Add("chart" + row + "" + column + ".bmp");
StackPanel stackpan1 = chartgridimage.ChildrenOfType<StackPanel>().FirstOrDefault(e => Grid.GetRow(e) == row && Grid.GetColumn(e) == column && e.Name.Equals("stackpan1"));
Telerik.Windows.Controls.Label label1 = stackpan1.ChildrenOfType<Telerik.Windows.Controls.Label>().FirstOrDefault(e => e.Name.Equals("label1"));
StackPanel stackpan2 = chartgridimage.ChildrenOfType<StackPanel>().FirstOrDefault(e => Grid.GetRow(e) == row && Grid.GetColumn(e) == column && e.Name.Equals("stackpan2"));
Telerik.Windows.Controls.Label label2 = stackpan2.ChildrenOfType<Telerik.Windows.Controls.Label>().FirstOrDefault(e => e.Name.Equals("label2"));
axisdata1.Add(label1.Content.ToString());
axisdata2.Add(label2.Content.ToString());
if (row == 7)
{
if (column == 0)
break;
}
}
}
}
答案 0 :(得分:1)
另一种看待你的问题的方法是,&#34;为什么它第一次渲染?&#34;。看起来有些事情你做的很奇怪,有些措施和安排可能会在第一时间起作用,然后再次失败。
如果我们将ExportCHARTtoBMP
内联到charttoimageprocess
,我们会看到以下代码段:
chart.UpdateLayout();
chart.Arrange(new Rect(new System.Windows.Size(chart.ActualWidth, chart.ActualHeight)));
chart.UpdateLayout();
chartx.Measure(new System.Windows.Size(double.PositiveInfinity, double.PositiveInfinity)); // from charttoimageprocess(...)
int chartW = (int)Math.Round(chartx.ActualWidth);
int chartH = (int)Math.Round(chartx.ActualHeight);
这里的问题是:
Arrange
和Measure
(通常是UpdateLayout
),除非您的代码是UIElement
派生的对象并且您正在铺设你的孩子(这与Grid
正在做的事情相冲突)Measure
和Arrange
(以及UpdateLayout
)都会影响布局,但实际上渲染结果布局变化。第一个问题可能是你的问题。如果您取消了上面的Arrange
/ Measure
/ UpdateLayout
次调用,那么您的代码可能会正常运行。
第二个问题也可能在起作用 - 您的代码可能正在运行但是图表的布局无效,而且他们没有时间重新渲染。 WPF中的渲染发生在与UI布局不同的线程上,并在检测到布局更新并尝试匹配特定帧速率(通常为30,60或120 fps)时运行。 (它暂停UI线程运行,有时可能在UpdateLayout期间运行)。要么第一个成功而另一个没有及时完成渲染显示,要么它使用缓存的位图图像,但其他人继续重新布局(因为当您重新测量时网格也会受到影响/安排其子项,这反过来使其对其他子项做同样的事情),导致每个后续图形尝试重新渲染越来越多次。通过从上面的代码中删除排列/测量,也可以消除这种情况。
最后,您可以通过将整个Grid
渲染到位图来绕过所有这些问题,然后根据简单的数学将该位图切割成6个较小的位图(因为它被分成3个相等大小的位图)列和2个相等大小的行)。