Skip to content

Commit ca3687d

Browse files
Updated the sample.
1 parent e60b7f6 commit ca3687d

38 files changed

+1335
-0
lines changed

App.xaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version = "1.0" encoding = "UTF-8" ?>
2+
<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
3+
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
4+
xmlns:local="clr-namespace:DualBarChartDemo"
5+
x:Class="DualBarChartDemo.App">
6+
<Application.Resources>
7+
<ResourceDictionary>
8+
<ResourceDictionary.MergedDictionaries>
9+
<ResourceDictionary Source="Resources/Styles/Colors.xaml" />
10+
<ResourceDictionary Source="Resources/Styles/Styles.xaml" />
11+
</ResourceDictionary.MergedDictionaries>
12+
</ResourceDictionary>
13+
</Application.Resources>
14+
</Application>

App.xaml.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
namespace DualBarChartDemo
2+
{
3+
public partial class App : Application
4+
{
5+
public App()
6+
{
7+
InitializeComponent();
8+
}
9+
10+
protected override Window CreateWindow(IActivationState? activationState)
11+
{
12+
return new Window(new AppShell());
13+
}
14+
}
15+
}

AppShell.xaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<Shell
3+
x:Class="DualBarChartDemo.AppShell"
4+
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
5+
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
6+
xmlns:local="clr-namespace:DualBarChartDemo"
7+
Title="DualBarChartDemo">
8+
9+
<ShellContent
10+
ContentTemplate="{DataTemplate local:MainPage}"
11+
Route="MainPage" />
12+
</Shell>

AppShell.xaml.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace DualBarChartDemo
2+
{
3+
public partial class AppShell : Shell
4+
{
5+
public AppShell()
6+
{
7+
InitializeComponent();
8+
}
9+
}
10+
}

DualBarChartDemo.csproj

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFrameworks>net9.0-android;net9.0-ios;net9.0-maccatalyst</TargetFrameworks>
5+
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net9.0-windows10.0.19041.0</TargetFrameworks>
6+
<!-- Uncomment to also build the tizen app. You will need to install tizen by following this: https://github.com/Samsung/Tizen.NET -->
7+
<!-- <TargetFrameworks>$(TargetFrameworks);net9.0-tizen</TargetFrameworks> -->
8+
9+
<!-- Note for MacCatalyst:
10+
The default runtime is maccatalyst-x64, except in Release config, in which case the default is maccatalyst-x64;maccatalyst-arm64.
11+
When specifying both architectures, use the plural <RuntimeIdentifiers> instead of the singular <RuntimeIdentifier>.
12+
The Mac App Store will NOT accept apps with ONLY maccatalyst-arm64 indicated;
13+
either BOTH runtimes must be indicated or ONLY macatalyst-x64. -->
14+
<!-- For example: <RuntimeIdentifiers>maccatalyst-x64;maccatalyst-arm64</RuntimeIdentifiers> -->
15+
16+
<OutputType>Exe</OutputType>
17+
<RootNamespace>DualBarChartDemo</RootNamespace>
18+
<UseMaui>true</UseMaui>
19+
<SingleProject>true</SingleProject>
20+
<ImplicitUsings>enable</ImplicitUsings>
21+
<Nullable>enable</Nullable>
22+
23+
<!-- Display name -->
24+
<ApplicationTitle>DualBarChartDemo</ApplicationTitle>
25+
26+
<!-- App Identifier -->
27+
<ApplicationId>com.companyname.dualbarchartdemo</ApplicationId>
28+
29+
<!-- Versions -->
30+
<ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
31+
<ApplicationVersion>1</ApplicationVersion>
32+
33+
<!-- To develop, package, and publish an app to the Microsoft Store, see: https://aka.ms/MauiTemplateUnpackaged -->
34+
<WindowsPackageType>None</WindowsPackageType>
35+
36+
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">15.0</SupportedOSPlatformVersion>
37+
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">15.0</SupportedOSPlatformVersion>
38+
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">21.0</SupportedOSPlatformVersion>
39+
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</SupportedOSPlatformVersion>
40+
<TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</TargetPlatformMinVersion>
41+
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'tizen'">6.5</SupportedOSPlatformVersion>
42+
</PropertyGroup>
43+
44+
<ItemGroup>
45+
<!-- App Icon -->
46+
<MauiIcon Include="Resources\AppIcon\appicon.svg" ForegroundFile="Resources\AppIcon\appiconfg.svg" Color="#512BD4" />
47+
48+
<!-- Splash Screen -->
49+
<MauiSplashScreen Include="Resources\Splash\splash.svg" Color="#512BD4" BaseSize="128,128" />
50+
51+
<!-- Images -->
52+
<MauiImage Include="Resources\Images\*" />
53+
<MauiImage Update="Resources\Images\dotnet_bot.png" Resize="True" BaseSize="300,185" />
54+
55+
<!-- Custom Fonts -->
56+
<MauiFont Include="Resources\Fonts\*" />
57+
58+
<!-- Raw Assets (also remove the "Resources\Raw" prefix) -->
59+
<MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
60+
</ItemGroup>
61+
62+
<ItemGroup>
63+
<PackageReference Include="Microsoft.Maui.Controls" Version="$(MauiVersion)" />
64+
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="9.0.0" />
65+
<PackageReference Include="Syncfusion.Maui.Toolkit" Version="1.0.5" />
66+
</ItemGroup>
67+
68+
</Project>

MainPage.xaml

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
3+
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
4+
x:Class="DualBarChartDemo.MainPage"
5+
xmlns:syncfusion="clr-namespace:Syncfusion.Maui.Toolkit.Charts;assembly=Syncfusion.Maui.Toolkit"
6+
xmlns:local="clr-namespace:DualBarChartDemo">
7+
8+
<ContentPage.BindingContext>
9+
<local:ChartViewModel />
10+
</ContentPage.BindingContext>
11+
12+
<ContentPage.Resources>
13+
<x:String x:Key="PathData" >M14.958001,14.880005C11.712001,15.658997 8.1829996,17.106995 7.4849997,19.033997 7.2039995,19.811005 7.4359999,20.733002 8.1600008,21.779007L10.726001,19.212997 12.006,20.494003 9.6400003,22.858994C10.162,23.057999,10.645,23.169006,11.071,23.169006L11.072,23.169006C11.734,23.169006 12.251,22.944 12.748,22.436996 14.151,21.003006 14.794,17.789993 14.958001,14.880005z M17.013,12.417999L17,13.643005C16.977001,15.863998 16.656002,21.304001 14.177001,23.835999 13.31,24.720993 12.266,25.169006 11.072,25.169006 10.174001,25.169006 9.1820002,24.891998 8.1260004,24.373001L5.2629995,27.237 3.9819994,25.957001 6.729001,23.210007C5.4420004,21.492004 5.059001,19.860992 5.604001,18.354004 6.915,14.729996 13.179,13.158005 15.811,12.651001z M2,11L2,30 20,30 20,11z M2,2L2,8 20,8 20,2z M0,0L22,0 22,8.1670074 22,11 22,24.843994 25,21.311996 25,9 29.313,3.6880035 31.710999,6.125 28,10.796997 28,23 22,28.990005 22,32 0,32 0,11 0,8.1670074z</x:String>
14+
</ContentPage.Resources>
15+
16+
<Border Margin="{OnPlatform Android=10,Default=25,iOS=10}"
17+
StrokeThickness="1" Stroke="Black"
18+
StrokeShape="RoundRectangle 15">
19+
20+
<syncfusion:SfCartesianChart HorizontalOptions="Fill"
21+
VerticalOptions="Fill"
22+
Margin="{OnPlatform Android=5,Default=15,iOS=5}">
23+
<syncfusion:SfCartesianChart.Resources>
24+
<DataTemplate x:Key="tooltipTemplate" >
25+
<Border BackgroundColor="#7bb4eb"
26+
Padding="8, 3, 8, 3"
27+
Stroke="Transparent">
28+
<StackLayout Orientation="Horizontal">
29+
<Label Text="{Binding Item.year, StringFormat='{}{0:yyyy}'}"
30+
TextColor="Black"
31+
FontSize="14"
32+
HorizontalOptions="Center"
33+
VerticalOptions="Center"/>
34+
<Label Text=" : "
35+
TextColor="Black"
36+
FontAttributes="Bold"
37+
FontSize="14"
38+
HorizontalOptions="Center"
39+
VerticalOptions="Center"/>
40+
<BoxView WidthRequest="5"
41+
BackgroundColor="Transparent"/>
42+
<Label Text="{Binding Item.yValue}"
43+
TextColor="Black"
44+
FontSize="14"
45+
HorizontalOptions="Center"
46+
VerticalOptions="Center"/>
47+
</StackLayout>
48+
</Border>
49+
</DataTemplate>
50+
</syncfusion:SfCartesianChart.Resources>
51+
<syncfusion:SfCartesianChart.Title>
52+
<Grid Padding="35,0,0,10">
53+
<Grid.ColumnDefinitions>
54+
<ColumnDefinition Width="Auto"/>
55+
<ColumnDefinition Width="*" />
56+
</Grid.ColumnDefinitions>
57+
<Path Grid.Column="0"
58+
Data="{StaticResource PathData}"
59+
Fill="Black"
60+
Stroke="Gray"
61+
StrokeThickness="1"
62+
HeightRequest="40"
63+
WidthRequest="40"
64+
VerticalOptions="Center"/>
65+
66+
<StackLayout Grid.Column="1" Orientation="Vertical" HorizontalOptions="Start">
67+
<Label Text="Building Variance Indicators in .NET MAUI Toolkit Charts to Visualize Natural Gas Price Volatility"
68+
FontAttributes="Bold"
69+
FontSize="{OnPlatform Android=12,Default=16,iOS=12}" />
70+
<Label Text="Natural Gas Price Volatility Analysis 2014-2023"
71+
FontSize="{OnPlatform Android=10,Default=12,iOS=10}" />
72+
</StackLayout>
73+
</Grid>
74+
</syncfusion:SfCartesianChart.Title>
75+
76+
<syncfusion:SfCartesianChart.TooltipBehavior>
77+
<syncfusion:ChartTooltipBehavior Background="#7bb4eb" />
78+
</syncfusion:SfCartesianChart.TooltipBehavior>
79+
80+
<syncfusion:SfCartesianChart.XAxes>
81+
<syncfusion:DateTimeAxis Interval="2" IntervalType="Years" >
82+
<syncfusion:DateTimeAxis.Title>
83+
<syncfusion:ChartAxisTitle Text="Time Period (Years)" />
84+
</syncfusion:DateTimeAxis.Title>
85+
<syncfusion:DateTimeAxis.MajorTickStyle>
86+
<syncfusion:ChartAxisTickStyle Stroke="Transparent" TickSize="0" />
87+
</syncfusion:DateTimeAxis.MajorTickStyle>
88+
<syncfusion:DateTimeAxis.AxisLineStyle>
89+
<syncfusion:ChartLineStyle Stroke="#888888" StrokeWidth="1"/>
90+
</syncfusion:DateTimeAxis.AxisLineStyle>
91+
</syncfusion:DateTimeAxis>
92+
</syncfusion:SfCartesianChart.XAxes>
93+
94+
<syncfusion:SfCartesianChart.YAxes>
95+
<syncfusion:NumericalAxis Interval="1" >
96+
<syncfusion:NumericalAxis.Title>
97+
<syncfusion:ChartAxisTitle Text="Price (USD per Million BTU)" />
98+
</syncfusion:NumericalAxis.Title>
99+
<syncfusion:NumericalAxis.MajorTickStyle>
100+
<syncfusion:ChartAxisTickStyle Stroke="Transparent" TickSize="0" />
101+
</syncfusion:NumericalAxis.MajorTickStyle>
102+
<syncfusion:NumericalAxis.AxisLineStyle>
103+
<syncfusion:ChartLineStyle StrokeWidth="1" />
104+
</syncfusion:NumericalAxis.AxisLineStyle>
105+
106+
</syncfusion:NumericalAxis>
107+
</syncfusion:SfCartesianChart.YAxes>
108+
109+
<syncfusion:SfCartesianChart.Series>
110+
<syncfusion:ColumnSeries ItemsSource="{Binding Data}"
111+
XBindingPath="year"
112+
YBindingPath="yValue"
113+
EnableTooltip="True"
114+
Fill="#7bb4eb"
115+
ShowDataLabels="False"
116+
TooltipTemplate="{StaticResource tooltipTemplate}"
117+
Label="Column Value">
118+
</syncfusion:ColumnSeries>
119+
<local:RangeColumnSeriesExt ItemsSource="{Binding Data}"
120+
XBindingPath="year"
121+
High="high"
122+
Low="low"
123+
EnableTooltip="False" />
124+
</syncfusion:SfCartesianChart.Series>
125+
</syncfusion:SfCartesianChart>
126+
</Border>
127+
</ContentPage>

MainPage.xaml.cs

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+

2+
using Syncfusion.Maui.Toolkit.Charts;
3+
using Syncfusion.Maui.Toolkit.Graphics.Internals;
4+
using System.Collections.ObjectModel;
5+
using Font = Microsoft.Maui.Graphics.Font;
6+
7+
namespace DualBarChartDemo
8+
{
9+
public partial class MainPage : ContentPage
10+
{
11+
12+
public MainPage()
13+
{
14+
InitializeComponent();
15+
}
16+
17+
}
18+
19+
public class RangeColumnSeriesExt : RangeColumnSeries
20+
{
21+
protected override ChartSegment CreateSegment()
22+
{
23+
return new RangeColumnSegmentExt();
24+
}
25+
}
26+
27+
public class RangeColumnSegmentExt : RangeColumnSegment
28+
{
29+
protected override void Draw(ICanvas canvas)
30+
{
31+
base.OnLayout();
32+
33+
// Skip drawing if segment isn't properly laid out or data is missing
34+
if (float.IsNaN(Left) || float.IsNaN(Top) || float.IsNaN(Right) || float.IsNaN(Bottom) ||
35+
Series is not RangeColumnSeriesExt || Item is not ChartDataModel dataPoint)
36+
return;
37+
38+
// Skip last segment or if there's no change
39+
if (Index == (Series.ItemsSource as ObservableCollection<ChartDataModel>)?.Count - 1 ||
40+
dataPoint.high == 0 || dataPoint.low == dataPoint.high)
41+
return;
42+
43+
// Calculate change direction and percentage
44+
bool isIncreasing = dataPoint.low < dataPoint.high;
45+
double changePercent = dataPoint.low != 0 ?
46+
((dataPoint.high - dataPoint.low) / Math.Abs(dataPoint.low)) * 100 : 0;
47+
48+
// Set color based on direction
49+
Color arrowColor = isIncreasing ? Color.FromArgb("#1CD01C") : Colors.Red;
50+
51+
// Save canvas state
52+
canvas.CanvasSaveState();
53+
54+
// Draw line with arrow
55+
float centerX = (Left + Right) / 2;
56+
canvas.StrokeColor = Colors.Black;
57+
canvas.StrokeSize = 1f;
58+
canvas.DrawLine(centerX, Top, centerX, Bottom);
59+
60+
// Draw arrow
61+
float arrowSize = 6;
62+
PathF arrowPath = new PathF();
63+
64+
if (isIncreasing)
65+
{
66+
arrowPath.MoveTo(centerX, Top);
67+
arrowPath.LineTo(centerX - arrowSize, Top + arrowSize);
68+
arrowPath.LineTo(centerX + arrowSize, Top + arrowSize);
69+
}
70+
else
71+
{
72+
arrowPath.MoveTo(centerX, Bottom);
73+
arrowPath.LineTo(centerX - arrowSize, Bottom - arrowSize);
74+
arrowPath.LineTo(centerX + arrowSize, Bottom - arrowSize);
75+
}
76+
77+
arrowPath.Close();
78+
canvas.FillColor = Colors.Black;
79+
canvas.FillPath(arrowPath);
80+
81+
string percentText = isIncreasing ?
82+
$"{Math.Abs(changePercent):0}%" :
83+
$"- {Math.Abs(changePercent):0}%";
84+
85+
float textY = isIncreasing ? Top - 20 : Bottom + 20;
86+
87+
canvas.FontColor = arrowColor;
88+
canvas.FontSize = 14;
89+
var fontFamily = "Bold";
90+
canvas.Font = new Font(fontFamily);
91+
92+
canvas.DrawString(percentText, centerX, textY, HorizontalAlignment.Center);
93+
94+
// Restore canvas state
95+
canvas.CanvasRestoreState();
96+
}
97+
}
98+
}

MauiProgram.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using Microsoft.Extensions.Logging;
2+
using Syncfusion.Maui.Toolkit.Hosting;
3+
4+
namespace DualBarChartDemo
5+
{
6+
public static class MauiProgram
7+
{
8+
public static MauiApp CreateMauiApp()
9+
{
10+
var builder = MauiApp.CreateBuilder();
11+
builder
12+
.UseMauiApp<App>()
13+
.ConfigureSyncfusionToolkit()
14+
.ConfigureFonts(fonts =>
15+
{
16+
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
17+
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
18+
});
19+
20+
#if DEBUG
21+
builder.Logging.AddDebug();
22+
#endif
23+
24+
return builder.Build();
25+
}
26+
}
27+
}

Model.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace DualBarChartDemo
8+
{
9+
public class ChartDataModel
10+
{
11+
public DateTime year { get; set; }
12+
public double yValue { get; set; }
13+
public double high { get; set; }
14+
public double low { get; set; }
15+
}
16+
}

0 commit comments

Comments
 (0)