4 Answers, 1 is accepted
0
Accepted
Hello Bhushan,
I'm not sure which product you're asking about since you mention Kendo and RadCartesianChart. The product you submitted this post under (UI for UWP) doesn't use Kendo components.
I will answer in the context of UI for UWP:
The UI for UWP suite doesn't explicitly have an export chart function, however this is very easy to do in a UWP application. You can render any UIElement to a jpg by using RenderTargetBitmap. See that documentation's example for the full code, here is how to use it for the Chart.
Just pass the chart into the RenderAsync method like this:
You can then encode the bitmap and share/save it as you see fit using the BitmapEncoder class. Note that this isn't directly related to Telerik UI for UWP components, so it falls outside the scope of Telerik Support.
That said, I built you a small demo that shows how to accomplish this (see screenshot and demo attached). The first button click renders the chart to a bitmap, the second button click saves it to a file.
Here is the code:
MainPage.xaml
MainPage.xaml.cs
Please let us know if you have any further questions. If this answer works for you, please consider marking this thread as answered.
Thank you for contacting support and for choosing Telerik by Progress!
Regards,
Lance | Tech Support Engineer, Sr.
Telerik by Progress
I'm not sure which product you're asking about since you mention Kendo and RadCartesianChart. The product you submitted this post under (UI for UWP) doesn't use Kendo components.
I will answer in the context of UI for UWP:
The UI for UWP suite doesn't explicitly have an export chart function, however this is very easy to do in a UWP application. You can render any UIElement to a jpg by using RenderTargetBitmap. See that documentation's example for the full code, here is how to use it for the Chart.
Just pass the chart into the RenderAsync method like this:
var renderTargetBitmap =
new
RenderTargetBitmap();
await renderTargetBitmap.RenderAsync(MyChart);
RenderOutputImage.Source = renderTargetBitmap;
You can then encode the bitmap and share/save it as you see fit using the BitmapEncoder class. Note that this isn't directly related to Telerik UI for UWP components, so it falls outside the scope of Telerik Support.
That said, I built you a small demo that shows how to accomplish this (see screenshot and demo attached). The first button click renders the chart to a bitmap, the second button click saves it to a file.
Here is the code:
MainPage.xaml
<
Grid
Background
=
"{ThemeResource ApplicationPageBackgroundThemeBrush}"
>
<
Grid.RowDefinitions
>
<
RowDefinition
Height
=
"Auto"
/>
<
RowDefinition
/>
<
RowDefinition
Height
=
"Auto"
/>
</
Grid.RowDefinitions
>
<
Grid.ColumnDefinitions
>
<
ColumnDefinition
/>
<
ColumnDefinition
/>
</
Grid.ColumnDefinitions
>
<
TextBlock
Text
=
"Telerik RadChart"
HorizontalAlignment
=
"Center"
Style
=
"{StaticResource TitleTextBlockStyle}"
/>
<
TextBlock
Text
=
"Output Image"
Grid.Column
=
"1"
HorizontalAlignment
=
"Center"
Style
=
"{StaticResource TitleTextBlockStyle}"
/>
<
chart:RadCartesianChart
x:Name
=
"MyChart"
Grid.Row
=
"1"
>
<
chart:RadCartesianChart.HorizontalAxis
>
<
chart:CategoricalAxis
/>
</
chart:RadCartesianChart.HorizontalAxis
>
<
chart:RadCartesianChart.VerticalAxis
>
<
chart:LinearAxis
/>
</
chart:RadCartesianChart.VerticalAxis
>
<
chart:BarSeries
x:Name
=
"MyBarSeries"
/>
</
chart:RadCartesianChart
>
<
Image
x:Name
=
"RenderOutputImage"
Grid.Column
=
"1"
Grid.Row
=
"1"
/>
<
Button
x:Name
=
"RenderButton"
Content
=
"Render Chart to Bitmap"
Margin
=
"20,10,20,30"
Grid.Row
=
"2"
Grid.ColumnSpan
=
"2"
HorizontalAlignment
=
"Center"
Click
=
"RenderToJpgButton_OnClick"
/>
<
Button
x:Name
=
"SaveButton"
Content
=
"Render Chart to Bitmap"
Margin
=
"20,10,20,30"
Grid.Row
=
"2"
Grid.ColumnSpan
=
"2"
HorizontalAlignment
=
"Center"
Visibility
=
"Collapsed"
Click
=
"SaveButton_OnClick"
/>
<
TextBlock
x:Name
=
"StatusTextBlock"
Text
=
"Click button to render Chart into bitmap"
Grid.Row
=
"2"
Grid.ColumnSpan
=
"2"
HorizontalAlignment
=
"Center"
VerticalAlignment
=
"Bottom"
/>
</
Grid
>
MainPage.xaml.cs
public
sealed
partial
class
MainPage : Page
{
private
RenderTargetBitmap rtb;
public
MainPage()
{
this
.InitializeComponent();
MyBarSeries.ItemsSource =
new
ObservableCollection<
double
> { 20, 30, 50, 10, 60, 40, 20, 80 };
}
private
async
void
RenderToJpgButton_OnClick(
object
sender, RoutedEventArgs e)
{
await RenderChartToBitmapAsync();
}
private
async
void
SaveButton_OnClick(
object
sender, RoutedEventArgs e)
{
await SaveBitmapAsync();
}
private
async Task RenderChartToBitmapAsync()
{
StatusTextBlock.Text = $
"starting render..."
;
rtb =
new
RenderTargetBitmap();
await rtb.RenderAsync(MyChart);
StatusTextBlock.Text = $
"render complete, setting Image source in UI..."
;
// Show the image in the UI
RenderOutputImage.Source = rtb;
StatusTextBlock.Text = $
"Rednering done! Click button to save to file"
;
RenderButton.Visibility = Visibility.Collapsed;
SaveButton.Visibility = Visibility.Visible;
}
private
async Task SaveBitmapAsync()
{
if
(rtb ==
null
)
{
StatusTextBlock.Text = $
"RenderTargetBitmap was null. Try again."
;
RenderButton.Visibility = Visibility.Visible;
SaveButton.Visibility = Visibility.Collapsed;
return
;
}
var pixelBuffer = await rtb.GetPixelsAsync();
var savePicker =
new
FileSavePicker();
savePicker.DefaultFileExtension =
".png"
;
savePicker.FileTypeChoices.Add(
".png"
,
new
List<
string
> {
".png"
});
savePicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
savePicker.SuggestedFileName =
"MyChart.png"
;
var saveFile = await savePicker.PickSaveFileAsync();
if
(saveFile ==
null
)
return
;
// Encode the image to the selected file on disk (docs https://msdn.microsoft.com/en-us/library/windows/apps/windows.graphics.imaging.bitmapencoder.aspx )
using
(var fileStream = await saveFile.OpenAsync(FileAccessMode.ReadWrite))
{
var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, fileStream);
encoder.SetPixelData(
BitmapPixelFormat.Bgra8,
BitmapAlphaMode.Ignore,
(
uint
)rtb.PixelWidth,
(
uint
)rtb.PixelHeight,
DisplayInformation.GetForCurrentView().LogicalDpi,
DisplayInformation.GetForCurrentView().LogicalDpi,
pixelBuffer.ToArray());
await encoder.FlushAsync();
}
StatusTextBlock.Text = $
"File Saved to {saveFile.Path}"
;
}
}
Please let us know if you have any further questions. If this answer works for you, please consider marking this thread as answered.
Thank you for contacting support and for choosing Telerik by Progress!
Regards,
Lance | Tech Support Engineer, Sr.
Telerik by Progress
Do you want to have your say when we set our development plans?
Do you want to know when a feature you care about is added or when a bug fixed?
Explore the
Telerik Feedback Portal
and vote to affect the priority of the items
0

Bhushan
Top achievements
Rank 1
answered on 02 Dec 2016, 05:55 AM
Hello Lance,
Thank you for your help.
I am using "UI for Universal Windows Platform" product in my UWP application.
I have tried your given solution and it works fine. Thank you.
Can we do the same thing in ViewModel instead of Code Behind.
Thanks.
0
Hello Bhushan,
I don't see why not. All you need from the View is the UIElement for the RenderTargetBitmap to do it's job.
Create a Command that passes a UIElement as it's parameter. A DelegateCommand is best for this type of thing. For your convenience, here is a DelegateCommand that I've written that works with and without a parameter:
With this, in your ViewModel you can create an instance of the command and the UIElement is passed to the action.
Then in the view, you can set up your Button to use the command and pass the UIElement:
I've updated my demo to use MVVM for everything and the rendering happens in MainPageViewModel.
Regards,
Lance | Tech Support Engineer, Sr.
Telerik by Progress
I don't see why not. All you need from the View is the UIElement for the RenderTargetBitmap to do it's job.
Create a Command that passes a UIElement as it's parameter. A DelegateCommand is best for this type of thing. For your convenience, here is a DelegateCommand that I've written that works with and without a parameter:
public
class
DelegateCommand : DelegateCommand<
object
>
{
public
DelegateCommand(Action execute, Func<
bool
> canExecute)
:
base
(_ => execute(), _ => canExecute())
{
if
(execute ==
null
)
throw
new
ArgumentNullException(nameof(execute));
if
(canExecute ==
null
)
throw
new
ArgumentNullException(nameof(canExecute));
}
public
DelegateCommand(Action execute)
:
this
(execute, () =>
true
)
{
}
}
public
class
DelegateCommand<T> : ICommand
{
private
Action<T> execute;
private
Func<T,
bool
> canExecute;
public
event
EventHandler CanExecuteChanged;
public
DelegateCommand(Action<T> execute, Func<T,
bool
> canExecute)
{
if
(execute ==
null
)
throw
new
ArgumentNullException(nameof(execute));
if
(canExecute ==
null
)
throw
new
ArgumentNullException(nameof(canExecute));
this
.execute = execute;
this
.canExecute = canExecute;
}
public
DelegateCommand(Action<T> execute)
:
this
(execute, _ =>
true
)
{
}
public
bool
CanExecute(
object
parameter)
{
if
(!(parameter
is
T) && parameter != (
object
)
default
(T))
return
false
;
return
canExecute((T)parameter);
}
public
void
Execute(
object
parameter)
{
execute((T)parameter);
}
public
void
NotifyCanExecuteChanged()
{
EventHandler eventHandler = CanExecuteChanged;
eventHandler?.Invoke(
this
, EventArgs.Empty);
}
}
With this, in your ViewModel you can create an instance of the command and the UIElement is passed to the action.
private
DelegateCommand<UIElement> renderChartCommand;
public
DelegateCommand<UIElement> RenderChartCommand
{
get
{
return
renderChartCommand ?? (renderChartCommand =
new
DelegateCommand<UIElement>(async (e) => await RenderElement(e))); }
}
private
async Task RenderElement(UIElement element)
{
// Do your rendering work here
}
Then in the view, you can set up your Button to use the command and pass the UIElement:
<
chart:RadCartesianChart
x:Name
=
"MyChart"
...>
<
Button
Command
=
"{Binding RenderChartCommand}"
CommandParameter
=
"{Binding ElementName=MyChart}"
/>
I've updated my demo to use MVVM for everything and the rendering happens in MainPageViewModel.
Regards,
Lance | Tech Support Engineer, Sr.
Telerik by Progress
Do you want to have your say when we set our development plans?
Do you want to know when a feature you care about is added or when a bug fixed?
Explore the
Telerik Feedback Portal
and vote to affect the priority of the items
0

Bhushan
Top achievements
Rank 1
answered on 05 Dec 2016, 05:42 AM
Hello lance,
Thank you for your help. :)
This is working as per expectations.