2015-07-11 22 views
15

Tôi đang viết ứng dụng giao diện điều khiển phía máy chủ trong C# /. Net 4.5 nhận dữ liệu và tạo hình ảnh biểu đồ tĩnh được lưu bởi máy chủ web.Hiển thị phía máy chủ của WPF UserControl

tôi chủ yếu sử dụng phương pháp này được mô tả ở đây: http://lordzoltan.blogspot.com/2010/09/using-wpf-to-render-bitmaps.html

Tuy nhiên, tôi đã thêm một mainContainer.UpdateLayout(); sau khi sắp xếp() sao cho các databindings sẽ cập nhật và hiển thị trong ảnh đã render, cũng như một Measure() trước khi nó cho tốt ... ah, tôi sẽ không đến đó.

Dưới đây là phương pháp mà không được vẽ:

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); 
    } 
} 

Các tham số mục tiêu để phương pháp này sẽ là một thể hiện của một WPF/XAML UserControl tôi đã thực hiện - khá đơn giản vào thời điểm này, chỉ cần một mạng lưới với một số text databinding đến một đối tượng ViewModel mà tôi đã gán cho DataContext.

Hình ảnh đã lưu trên đĩa có vẻ là ngoại lệ tốt cho đối tượng Lô đất OxyPlot - nó hoàn toàn màu trắng.

Bây giờ, khi tôi ở trong nhà thiết kế trong Visual Studio 2013, tôi có thể thấy nó. Tôi đã thêm một DataContext thời gian thiết kế giống như đối tượng mà tôi sử dụng khi chạy (đây là một spike tôi đang làm - viewmodel không ở dạng cuối cùng của nó, chỉ có một bó dữ liệu mặc định trong khi tôi tìm ra). Trong nhà thiết kế, tôi thấy biểu đồ như OxyPlot vẽ nó.

Có điều gì đặc biệt mà tôi cần làm để có được kết xuất cũng chứa biểu đồ OxyPlot này không? Nó là nhiều hơn hoặc ít hơn điểm của tập thể dục vì vậy nó sẽ là tuyệt vời để thực sự làm cho nó hiển thị!

Cảm ơn trước vì bất kỳ thông tin chi tiết và đề xuất nào!

+0

Givens mảng rộng các nền tảng được hỗ trợ, tôi sẽ nghi ngờ rằng vấn đề là ở cách thức kiểm soát OxyPlot WPF đã được thực hiện. Có lẽ nó là một điều khiển WinForms nhúng trong một điều khiển WPF, có thể có vấn đề. Tôi không biết liệu điều đó có giúp ích gì không. –

+0

Bạn có thể đúng về điều này, tất nhiên - có khả năng là không có cách nào để làm điều này mà không có sự kiểm soát tồn tại trong một môi trường WPF đầy đủ. Trong trường hợp đó, tôi sẽ đi tìm một thành phần biểu đồ khác.Tuy nhiên, nếu tôi chỉ có thể tìm hiểu những gì các nhà thiết kế làm tôi không, sau đó tôi hy vọng rằng tôi có thể kích hoạt nó để sơn chính nó .. –

+0

@swiszcz: Bạn có thể giải thích tại sao các câu trả lời được cung cấp ở đây sẽ không làm việc cho bạn? –

Trả lời

5

Nếu bạn đang ràng buộc chính xác dữ liệu trong thời gian chạy là tốt, thì nó sẽ hoạt động.

enter image description here

[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; 
    } 
} 
+0

Cảm ơn câu trả lời của bạn, và xin lỗi vì nhận xét muộn của tôi về nó. Vâng, ví dụ của bạn rõ ràng là hoạt động. Và tôi có hai ví dụ (mã độc quyền, không may), nơi nó không ... Tôi hy vọng tôi sẽ tìm thấy một thời gian trong một tương lai gần để tạo ra một ví dụ tái sản xuất tối thiểu để tìm hiểu khi nào (và tại sao) nó không hoạt động. –

+0

Bạn đang rất hoan nghênh. Xin lỗi vì đã nghe về điều đó ... Chắc chắn đăng một [MCVE] (https://stackoverflow.com/help/mcve) bất cứ khi nào bạn có cơ hội, và gửi cho tôi một lưu ý về nó, tôi sẽ rất vui khi nhìn vào nó lần nữa. Chúc mừng. – jsanalytics

+0

Cảm ơn! Tôi sẽ! –

3

Tôi không biết gì về OxyPlat này, nhưng tôi biết rằng hầu hết biểu đồ là ofte n được hiển thị bằng API phần cứng. Tăng tốc phần cứng thường dễ bị lỗi khi làm việc bên ngoài môi trường dự kiến ​​(ví dụ: khách hàng hiển thị cửa sổ Màn hình có thể nhìn thấy).

Ngày khởi tạo ứng dụng, hãy thử tắt tăng tốc phần cứng:

RenderOptions.ProcessRenderMode = RenderMode.SoftwareOnly; 
+0

Ứng dụng của chúng tôi rất nặng, do đó, việc loại bỏ thêm hỗ trợ phần cứng sẽ không phải là ý tưởng hay nhất. Xin lỗi vì nhận xét muộn về câu trả lời của bạn! –

Các vấn đề liên quan