我正在用 C#/.Net 4.5 编写一个服务器端控制台应用程序,它获取一些数据并创建静态图表图像,这些图像被保存以供网络服务器显示。
我主要使用此处描述的方法: http://lordzoltan.blogspot.com/2010/09/using-wpf-to-render-bitmaps.html
但是,我添加了一个 mainContainer.UpdateLayout();在 Arrange() 之后,以便数据绑定(bind)将更新并在渲染图像中可见,以及在它之前的 Measure() 永远......啊,我不会去那里。
这是执行渲染的方法:
void RenderAndSave(UIElement target, string filename, int width, int height)
{
var mainContainer = new Grid
{
HorizontalAlignment = HorizontalAlignment.Stretch,
VerticalAlignment = VerticalAlignment.Stretch
};
mainContainer.Children.Add(target);
mainContainer.Measure(new Size(width, height));
mainContainer.Arrange(new Rect(0, 0, width, height));
mainContainer.UpdateLayout();
var encoder = new PngBitmapEncoder();
var render = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32);
render.Render(mainContainer);
encoder.Frames.Add(BitmapFrame.Create(render));
using (var s = File.Open(filename, FileMode.Create))
{
encoder.Save(s);
}
}
该方法的目标参数将是我创建的 WPF/XAML UserControl 实例 - 在这一点上相当简单,只是一个网格,其中包含一些文本数据绑定(bind)到我分配给 DataContext 的 ViewModel 对象。
磁盘上保存的图像看起来不错,除了 OxyPlot Plot 对象 - 它完全是白色的。
现在,当我在 Visual Studio 2013 的设计器中时,我可以看到它。我添加了一个设计时 DataContext,它与我在运行时使用的对象相同(这是我正在做的一个峰值——viewmodel 还不是最终形式,在我解决问题时只有一堆默认数据).在设计器中,我看到 OxyPlot 绘制的图表。
为了让我的渲染也包含这个 OxyPlot 图表,我需要做些什么特别的事情吗?这或多或少是练习的重点,所以真正让它出现会很棒!
提前感谢您的任何见解和建议!
最佳答案
如果您也在运行时正确绑定(bind)数据,那么它应该可以工作。
[STAThread]
static void Main(string[] args)
{
string filename = "wpfimg.png";
RenderAndSave(new UserControl1(), filename, 300, 300);
PictureBox pb = new PictureBox();
pb.Width = 350;
pb.Height = 350;
pb.Image = System.Drawing.Image.FromFile(filename);
Form f = new Form();
f.Width = 375;
f.Height = 375;
f.Controls.Add(pb);
f.ShowDialog();
}
XAML:
<UserControl x:Class="WpfApp92.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:oxy="http://oxyplot.org/wpf"
xmlns:local="clr-namespace:WpfApp92"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<oxy:PlotView Model="{Binding Model}"/>
</Grid>
</UserControl>
CS:
public partial class UserControl1 : UserControl
{
public PlotModel Model { get; set; }
public UserControl1()
{
InitializeComponent();
Model = new PlotModel();
Model.LegendBorderThickness = 0;
Model.LegendOrientation = LegendOrientation.Horizontal;
Model.LegendPlacement = LegendPlacement.Outside;
Model.LegendPosition = LegendPosition.BottomCenter;
Model.Title = "Simple model";
var categoryAxis1 = new CategoryAxis();
categoryAxis1.MinorStep = 1;
categoryAxis1.ActualLabels.Add("Category A");
categoryAxis1.ActualLabels.Add("Category B");
categoryAxis1.ActualLabels.Add("Category C");
categoryAxis1.ActualLabels.Add("Category D");
Model.Axes.Add(categoryAxis1);
var linearAxis1 = new LinearAxis();
linearAxis1.AbsoluteMinimum = 0;
linearAxis1.MaximumPadding = 0.06;
linearAxis1.MinimumPadding = 0;
Model.Axes.Add(linearAxis1);
var columnSeries1 = new ColumnSeries();
columnSeries1.StrokeThickness = 1;
columnSeries1.Title = "Series 1";
columnSeries1.Items.Add(new ColumnItem(25, -1));
columnSeries1.Items.Add(new ColumnItem(137, -1));
columnSeries1.Items.Add(new ColumnItem(18, -1));
columnSeries1.Items.Add(new ColumnItem(40, -1));
Model.Series.Add(columnSeries1);
var columnSeries2 = new ColumnSeries();
columnSeries2.StrokeThickness = 1;
columnSeries2.Title = "Series 2";
columnSeries2.Items.Add(new ColumnItem(12, -1));
columnSeries2.Items.Add(new ColumnItem(14, -1));
columnSeries2.Items.Add(new ColumnItem(120, -1));
columnSeries2.Items.Add(new ColumnItem(26, -1));
Model.Series.Add(columnSeries2);
DataContext = this;
}
}
关于c# - WPF UserControl 的服务器端渲染,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31355609/