[英]Creating WriteableBitmap form chart issue
I have a problem when trying to create writeable bitmap form Silverlight toolkit Graph. 尝试创建可写位图表单Silverlight工具包图时出现问题。
When using textBlock, everything is fine, but after trying to use Chart, generated bitmap is empty :( . 使用textBlock时,一切都很好,但是尝试使用Chart之后,生成的位图为空:(。
var data = new List<Point>(100);
for (int i = 0; i < 100; i++)
{
data.Add(new Point(i, Math.Sin(i * Math.PI / 50)));
}
Chart chart_ = new Chart()
{
Name = "Chart",
Width = 512,
Height = 512
};
LineSeries line = new LineSeries()
{
Name = "Line",
Title = "test",
IndependentValuePath = "X",
DependentValuePath = "Y",
ItemsSource = data
};
chart_.Series.Add(line);
This code creates chart with sinusoid in it. 此代码创建包含正弦曲线的图表。 Then Im trying to create bitmap from it.
然后我试图从中创建位图。
LayoutRoot.Children.Add(chart_); // I tried to add chart_ to visual tree, It doesn't help
//creates bitmap
ScaleTransform t = new ScaleTransform() { ScaleX = 1.0, ScaleY = 1.0 };
//bitmap = new WriteableBitmap(chart_, t); Tried it also with this way
bitmap = new WriteableBitmap(512, 512);
bitmap.Render(chart_, t);
texture = new Texture2D(GraphicsDeviceManager.Current.GraphicsDevice, bitmap.PixelWidth, bitmap.PixelHeight, false, SurfaceFormat.Color);
bitmap.CopyTo(texture);
All this code creates Empty Bitmap.But when I use TextBlock or some primitives like Ellipse, everything works. 所有这些代码都创建了Empty Bitmap,但是当我使用TextBlock或诸如Ellipse之类的原语时,一切正常。 Im sure, that code generating chart is fine, cause chart is generated fine in Silverlight control.
我确定代码生成图表很好,因为在Silverlight控件中生成图表很好。
EDIT: I tried to create bitmap this way, but it dont help. 编辑:我试图以这种方式创建位图,但没有帮助。
chart_.InvalidateMeasure();
bitmap = new WriteableBitmap(512, 512);
bitmap.Render(chart_, null);
bitmap.Invalidate();
EDIT 2: I don't want graph to be in visual tree. 编辑2:我不希望图形在视觉树中。 I just need generate image of it an than use it in XNA part of my application.
我只需要生成它的映像即可,而不是在我的应用程序的XNA部分中使用它。
Just a couple of small changes, but I suspect the big change is manually adding a reference to System.Windows.Controls after using NuGet to add the Charting package. 只是几个小的更改,但是我怀疑最大的更改是在使用NuGet添加Charting程序包之后手动添加对System.Windows.Controls的引用。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Controls.DataVisualization.Charting;
using System.Windows.Media.Imaging;
namespace SilverlightApplication1
{
public partial class MainPage : UserControl
{
Chart chart_;
public MainPage()
{
InitializeComponent();
var data = new List<Point>(100);
for (int i = 0; i < 100; i++)
{
data.Add(new Point(i, Math.Sin(i * Math.PI / 50)));
}
chart_ = new Chart()
{
Name = "Chart",
Width = 512,
Height = 512
};
LineSeries line = new LineSeries()
{
Name = "Line",
Title = "test",
IndependentValuePath = "X",
DependentValuePath = "Y",
ItemsSource = data
};
chart_.Series.Add(line);
LayoutRoot.Children.Add(chart_); // I tried to add chart_ to visual tree, It doesn't help
}
private void LayoutRoot_Loaded(object sender, RoutedEventArgs e)
{
//creates bitmap
WriteableBitmap bitmap;
ScaleTransform t = new ScaleTransform() { ScaleX = 1.0, ScaleY = 1.0 };
//bitmap = new WriteableBitmap(chart_, t); Tried it also with this way
bitmap = new WriteableBitmap(512, 512);
bitmap.Render(chart_, t);
//texture = new Texture2D(GraphicsDeviceManager.Current.GraphicsDevice, bitmap.PixelWidth, bitmap.PixelHeight, false, SurfaceFormat.Color);
//bitmap.CopyTo(texture);
image1.Source = bitmap;
}
}
}
And 和
<UserControl x:Class="SilverlightApplication1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400"
xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit">
<Grid x:Name="LayoutRoot" Background="White" Loaded="LayoutRoot_Loaded">
<Image Height="150" HorizontalAlignment="Left" Margin="97,109,0,0" Name="image1" Stretch="Fill" VerticalAlignment="Top" Width="200" />
</Grid>
</UserControl>
That should get you going... 那应该让你走...
Don't forget to delete all of the attempted workarounds - I don't think any of them are necessary. 不要忘记删除所有尝试的解决方法-我认为没有任何必要。 The only code I did not use from your example had to do with the textures - I didn't know what to do with that and it wasn't the problem you were having anyways...
我在您的示例中没有使用的唯一代码与纹理有关-我不知道该怎么做,这也不是您遇到的问题...
David 大卫
I believe that by the time you are creating WriteableBitmap object & calling Render method, Chart has not be rendered yet. 我相信,当您创建WriteableBitmap对象并调用Render方法时,Chart尚未呈现。 You can check this by moving these lines of code to some other event like Button_Click etc. Have a look at below codes as it is creating the WriteableBitmap and then passes it to image control as source....
您可以通过将这些代码行移至其他事件(如Button_Click等)来进行检查。在创建WriteableBitmap并将其作为源传递给图像控件时,请查看以下代码。
XAML Code..... XAML代码.....
<UserControl x:Class="TryBitmap.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400"
xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit">
<Grid x:Name="LayoutRoot" Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="35"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Button Grid.Row="0" Height="25" Width="100" Content="Capture" Click="Button_Click"/>
<Grid x:Name="grdGraphs" Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Image x:Name="img" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</Grid>
Code Behind.... 代码背后...
public partial class MainPage : UserControl
{
private Chart chart_;
public MainPage()
{
InitializeComponent();
Loaded += new RoutedEventHandler(MainPage_Loaded);
}
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
var data = new List<Point>(100);
for (int i = 0; i < 100; i++)
{
data.Add(new Point(i, Math.Sin(i * Math.PI / 50)));
}
chart_ = new Chart()
{
Name = "Chart",
Width = 512,
Height = 512
};
LineSeries line = new LineSeries()
{
Name = "Line",
Title = "test",
IndependentValuePath = "X",
DependentValuePath = "Y",
ItemsSource = data
};
chart_.Series.Add(line);
chart_.SetValue(Grid.ColumnProperty, 0);
grdGraphs.Children.Add(chart_);
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var bitmap = new WriteableBitmap((int)(chart_.RenderSize.Width), (int)(chart_.RenderSize.Height));
bitmap.Render(chart_, new MatrixTransform());
bitmap.Invalidate();
img.Source = bitmap;
}
}
I'm afraid this is only going to be half an answer. 恐怕这只能解决一半。 I can solve your immediate problem but I'm afraid you'll just end up with another one I haven't managed to solve.
我可以解决您的迫在眉睫的问题,但是恐怕您会遇到另一个我没有解决的问题。
Creating the bitmap after a call to Dispatcher.BeginInvoke
should ensure that your bitmap isn't completely blank, ie: 在调用
Dispatcher.BeginInvoke
之后创建位图应确保您的位图不是完全空白,即:
// do stuff with chart_ ...
Dispatcher.BeginInvoke(() =>
{
bitmap = new WriteableBitmap(512, 512);
bitmap.Render(chart_, null);
bitmap.Invalidate();
// At this point, the bitmap shouldn't be blank.
});
However, the results of this likely to be less than satisfactory. 但是,这样做的结果可能不太令人满意。 I ran your code and I found that the LineSeries was missing from the chart image, although the rest of the chart was there.
我运行了您的代码,发现图表图像中缺少LineSeries,尽管图表的其余部分在那里。 This remained true even after I set all
Duration
s of the various animations in the ControlTemplate
for the LineSeries
to 0 and additionally set the following properties on the chart: 即使我将
LineSeries
的ControlTemplate
中的各种动画的所有Duration
都设置为0,并在图表上另外设置了以下属性,也仍然如此:
chart_.AnimationSequence = AnimationSequence.Simultaneous;
chart_.TransitionDuration = new TimeSpan(0);
I tried wrapping the WriteableBitmap operations in further calls to Dispatcher.BeginInvoke()
, and after doing this the data points started to appear more clearly. 我尝试将WriteableBitmap操作包装在对
Dispatcher.BeginInvoke()
进一步调用中,然后完成后,数据点开始显得更加清晰。 However, I can't believe that an approach like this is the right solution to the problem. 但是,我无法相信这样的方法是解决问题的正确方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.