Chart of the Week: Create a .NET MAUI Column Chart to Visualize which Milk Is the Most Sustainable
Tags: dotnetmaui, chart, mobile, productivity
Published: 2024-03-08 04:40:27

---
title: Chart of the Week: Create a .NET MAUI Column Chart to Visualize which Milk Is the Most Sustainable
published: true
date: 2024-03-06 12:26:57 UTC
tags: dotnetmaui, chart, mobile, productivity
canonical_url: https://www.syncfusion.com/blogs/post/maui-columnchart-sustainable-milk.aspx
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/triy36fz41yqile0umg6.png
---
Welcome to the  **Chart of the Week**  blog series!

Today, we will explore the statistics of the most sustainable kinds of milk using the Syncfusion [.NET MAUI Column Chart](https://www.syncfusion.com/maui-controls/maui-cartesian-charts/chart-types/maui-column-chart "Syncfusion .NET MAUI Column Chart").

The [.NET MAUI Column Chart](https://help.syncfusion.com/maui/cartesian-charts/column "Getting started with .NET MAUI Column Chart"), a vertical bar chart, uses vertical bars (called columns) to display values for one or more items. The column chart is likely the most common chart type being used. Points from the series are drawn as columns next to each other. The chart supports zooming, scrolling, tooltips, and selection.

## Exploring environmental impact

Plant-based milks like soy, rice, oat, and almond are increasingly popular due to concerns about animal welfare, dietary restrictions, and climate impact. So, determining their environmental friendliness compared to dairy milk is important. Generally, nondairy options surpass cow’s milk in carbon emissions, land use, and water consumption.

The processes involved in creating and shipping almond, oat, soy, and rice milk emit significantly less carbon than dairy milk. Almond milk is the lowest at 0.7kg per liter, followed by oat (0.9kg), soy (1kg), and rice (1.2kg). Plant-based options also require less land, ranging from 0.3 to 0.8 square meters per liter, compared to nine square meters for cow milk.

Contrary to popular belief, the production of almond milk uses less water than dairy, with 371 liters of water per liter of milk compared to 628 liters of water for dairy. Rice milk needs 270 liters of water, while soy and oats are even more efficient, needing only 28 and 48 liters, respectively.

## Charting overall environmental impact

Notably, the production of alternative milks like soy and oat has minimal environmental impact compared to dairy, with factors like packaging and transportation becoming significant contributors to their ecological footprint. This comprehensive analysis underscores the importance of considering the entire life cycle of milk production.

The following chart visually presents the data discussed, providing a clear comparison of sustainability numbers between dairy and alternative milk.

![Visualizing the most sustainable milk data using .NET MAUI Column Chart](https://www.syncfusion.com/blogs/wp-content/uploads/2024/03/Visualizing-the-most-sustainable-milk-data-using-.NET-MAUI-Column-Chart.png)Now, let’s explore the steps involved in showcasing these details using the Syncfusion .NET MAUI Column Chart.

## Step 1: Gather data for milk

Before proceeding, we need to gather data on the different kinds of milk from the [BBC Report](https://www.bbc.com/future/article/20200207-which-milk-alternative-should-we-be-drinking "BBC Report") for our column chart.

## Step 2: Populate the data for the chart

To illustrate the sustainability of different milk types based on distinct factors, we will create a class named **MilkSourceModel**. This class will encompass the following attributes:

- **Source** : Signifying the various plant types utilized in milk production.
- **WaterQuantity** : Storing data on the volume of water consumed in milk production.
- **CO2Emission** : Storing data on carbon emissions produced during milk production.

Refer to the next code example for further clarification.

```csharp
public class MilkSourceModel
{
       public string Source { get; set; }
       public double WaterQuantity { get; set; }
       public double CO2Emission { get; set; }

       public MilkSourceModel(string source, double waterQuantity, double cO2Emission)
       {
           Source = source;
           WaterQuantity = waterQuantity;
           CO2Emission = cO2Emission;
       }
}
```

Next, we’ll generate the data collection illustrating the milk production details using the **MilkSourceData** class with the **Data** property.

Refer to the following code example.

```csharp
public class MilkSourceData : INotifyPropertyChanged
{
     public List<MilkSourceModel> Data { get; set; }

     public MilkSourceData()
     {
          Data = new List<MilkSourceModel>
          {
                new MilkSourceModel("Cow", 628, 3.2),
                new MilkSourceModel("Almond", 371, 0.7),
                new MilkSourceModel("Rice", 270, 1.2),
                new MilkSourceModel("Oat", 48, 0.9),
                new MilkSourceModel("Soy", 28, 1.0),
          };
         
     }
}
```

## Step 3: Configure the Syncfusion .NET MAUI Cartesian Charts

Let’s configure the Syncfusion .NET MAUI Cartesian Charts control using this [documentation](https://help.syncfusion.com/maui/cartesian-charts/getting-started "Getting started with .NET MAUI Charts").

Refer to the following code example.

```xml
<chart:SfCartesianChart>

   <chart:SfCartesianChart.XAxes>
       <chart:CategoryAxis>
       </chart:CategoryAxis>
   </chart:SfCartesianChart.XAxes>

   <chart:SfCartesianChart.YAxes>
       <chart:NumericalAxis>
       </chart:NumericalAxis>
   </chart:SfCartesianChart.YAxes>

</chart:SfCartesianChart>
```

## Step 4: Data binding for column chart visualization

Next, we create a column chart to represent the various types of milk. For this purpose, initialize the column chart in the code-behind and segment it as necessary.

Refer to the following code example.

```csharp
public class ColumnSeriesExt : ColumnSeries
{

}

public class ColumnSegmentExt : ColumnSegment
{
        
}
```

To bind the data to the chart, use a customized column instance. Bind the **Data** collection to the **ItemSource** property. The **XBindingPath** and **YBindingPath** properties should be associated with the **Source**  and **WaterQuantity** properties, respectively.

```xml
<model:ColumnSeriesExt ItemsSource="{Binding Data}" XBindingPath="Source" YBindingPath="WaterQuantity">

</model:ColumnSeriesExt>
```

## Step 5: Customize the column chart

Create an extension of the standard **ColumnSeries** with the **ColumnSeriesExt** class. Within this class, override the **CreateSegment** method. This is a crucial step that enables the creation of a distinct **ColumnSegmentExt** instance, allowing the chart to display specialized segments.

```csharp
public class ColumnSeriesExt : ColumnSeries
{
     protected override ChartSegment CreateSegment()
     {
         return new ColumnSegmentExt();
     }
}
```

Next, implement the **ColumnSegmentExt** class as a derivative of **ColumnSegment**. This class contains the drawing logic for the custom column shape, resulting in a visually appealing and personalized column chart.

For a detailed example, please refer to the following code example.

```csharp
public class ColumnSegmentExt : ColumnSegment
{
    protected override void Draw(ICanvas canvas)
    {
        if (Series is CartesianSeries series && series.ActualYAxis is NumericalAxis yAxis)
        {
            var top = yAxis.ValueToPoint(Convert.ToDouble(yAxis.Maximum ?? double.NaN));
            var trackRect = new RectF() { Left = Left, Top = (float)top, Right = Right, Bottom = Bottom };
            DrawTrackPath(canvas, trackRect);
            canvas.SaveState();
            DrawColumn(canvas);
            canvas.RestoreState();
        }
    }

    private void DrawColumn(ICanvas canvas)
    {
        var path = new PathF();

        #if ANDROID || IOS
        path.MoveTo(Left + 20, Bottom);
        path.LineTo(Right - 20, Bottom);
        path.LineTo(Right - 20, Top);
        path.LineTo(Left + 20, Top);
        path.Close();
        
        #elif WINDOWS || MACCATALYST
        path.MoveTo(Left + 10, Bottom);
        path.LineTo(Right - 10, Bottom);
        path.LineTo(Right - 10, Top);
        path.LineTo(Left + 10, Top);
        path.Close();
        
        #endif
        var color = (Fill is SolidColorBrush brush) ? brush.Color : Colors.Transparent;
        canvas.FillColor = color;
        canvas.FillPath(path);
    }

    private void DrawTrackPath(ICanvas canvas, RectF trackRect)
    {
        var path = new PathF();

        #if ANDROID || IOS
        path.MoveTo(Left + 20, Bottom);
        path.LineTo(Right - 20, Bottom);
        path.LineTo(Right - 20, trackRect.Top + 10);
        path.LineTo(Right - 40, trackRect.Top + 5);
        path.LineTo(Right - 40, trackRect.Top);
        path.LineTo(Left + 40, trackRect.Top);
        path.LineTo(Left + 40, trackRect.Top + 5);
        path.LineTo(Left + 20, trackRect.Top + 10);
        path.Close();

        #elif WINDOWS || MACCATALYST
        path.MoveTo(Left + 10, Bottom);
        path.LineTo(Right - 10, Bottom);
        path.LineTo(Right - 10, trackRect.Top + 30);
        path.LineTo(Right - 30, trackRect.Top + 15);
        path.LineTo(Right - 30, trackRect.Top);
        path.LineTo(Left + 30, trackRect.Top);
        path.LineTo(Left + 30, trackRect.Top + 15);
        path.LineTo(Left + 10, trackRect.Top + 30);
        path.Close();
        
        #endif
        canvas.FillColor = Color.FromRgb(243, 241, 255);
        canvas.FillPath(path);
    }
}
```

## Step 6: Customize the chart appearance

Let’s enhance the .NET MAUI column chart by customizing its properties and style to improve the data readability.

### Customizing the chart title

You can customize the chart title to make the chart more visually appealing and informative like in the following code example.

```xml
<chart:SfCartesianChart.Title>
 <Grid>
  <Grid.ColumnDefinitions>
   <ColumnDefinition Width="2*" />
   <ColumnDefinition Width="*" />
  </Grid.ColumnDefinitions>
  <Grid Margin="0,0,0,50" Grid.Column="0">
   <Grid.ColumnDefinitions>
    <ColumnDefinition Width="13"/>
    <ColumnDefinition Width="*"/>
   </Grid.ColumnDefinitions>
   <StackLayout Grid.RowSpan="2" Margin="0,5,0,0" Orientation="Vertical" BackgroundColor="#9BD241" />
   <StackLayout Grid.Column="1" Margin="5,0,0,0" HorizontalOptions="Start" Orientation="Vertical">
    <Label Text="Which Milk Is the Most Sustainable?" FontSize="Large" FontAttributes="Bold" TextColor="#666666" FontFamily="AntaRegular"/>
    <Label Text="Based on quantity of water used and CO₂ emitted per liter of milk" FontSize="17" TextColor="Gray" Margin="0,2,0,0" FontFamily="AntaRegular"/>
   </StackLayout>
  </Grid>
                    
  <VerticalStackLayout HorizontalOptions="End" Margin="40,0,0,0" Grid.Column="1">
   <Label Text="CO₂ Emission (in kg)" FontSize="16" FontFamily="AntaRegular" HorizontalOptions="Center" Margin="0,0,0,5"/>

   <Frame BorderColor="#031257" CornerRadius="5" Background="#0DC3ECB2" WidthRequest="{OnPlatform Android=165,iOS=165,Default=180}" Padding="5">
    <Grid>
     <Grid.ColumnDefinitions>
      <ColumnDefinition/>
      <ColumnDefinition/>
      <ColumnDefinition/>
     </Grid.ColumnDefinitions>
     <Image Grid.Row="1" Grid.Column="0" Source="{Binding SourceImage}" Margin="10,0,0,0" HeightRequest="{OnPlatform Android=50,iOS=50, Default=50}"
WidthRequest="{OnPlatform Android=50,iOS=50, Default=50}"/>
     <Image Grid.Row="1" Grid.Column="1" Source="right.png" Margin="15,0,0,0" HeightRequest="50" WidthRequest="40" VerticalOptions="Center"/>
     <Label Grid.Row="1" Grid.Column="2" Text="{Binding EmissionText}" FontFamily="AntaRegular" FontSize="18" Margin="-20,0,-25,0" HorizontalTextAlignment="Center" VerticalTextAlignment="Center"/>
     </Grid>
    </Frame>
  </VerticalStackLayout>
 </Grid>
</chart:SfCartesianChart.Title>
```

### Customizing the chart axis

You can customize the chart axis using the following properties:

- **ShowMajorGridLines** : Adjusts the visibility of the major grid lines.
- **LabelStyle** : Modifies the style of the axis labels.
- **AxisLineStyle** : Alters the style of the axis line.
- **MajorTickStyle** : Changes the style of the major tick lines.
- **Title** : Customizes the appearance of the axis title.

Refer to the following code example.

```xml
<chart:SfCartesianChart.XAxes>
 <chart:CategoryAxis ShowMajorGridLines="False">
 <chart:CategoryAxis.LabelStyle>
   <chart:ChartAxisLabelStyle FontFamily="AntaRegular" TextColor="Black" FontSize="14"/>
 </chart:CategoryAxis.LabelStyle>

 <chart:CategoryAxis.AxisLineStyle>
   <chart:ChartLineStyle StrokeWidth ="0"/>
 </chart:CategoryAxis.AxisLineStyle>

  <chart:CategoryAxis.MajorTickStyle>
   <chart:ChartAxisTickStyle StrokeWidth ="0"/>
  </chart:CategoryAxis.MajorTickStyle>
 </chart:CategoryAxis>
</chart:SfCartesianChart.XAxes>

<chart:SfCartesianChart.YAxes>
 <chart:NumericalAxis ShowMajorGridLines="False" Maximum="800">
  <chart:NumericalAxis.Title>
   <chart:ChartAxisTitle Text="Water use (liters)" FontSize="20" TextColor="Black" FontFamily="AntaRegular" Margin="0,-50,0,0"/>
  </chart:NumericalAxis.Title>

  <chart:NumericalAxis.LabelStyle>
   <chart:ChartAxisLabelStyle TextColor="Transparent"/>
  </chart:NumericalAxis.LabelStyle>

  <chart:NumericalAxis.AxisLineStyle>
   <chart:ChartLineStyle StrokeWidth ="0"/>
  </chart:NumericalAxis.AxisLineStyle>

  <chart:NumericalAxis.MajorTickStyle>
   <chart:ChartAxisTickStyle StrokeWidth ="0"/>
  </chart:NumericalAxis.MajorTickStyle>
 </chart:NumericalAxis>
</chart:SfCartesianChart.YAxes>
```

### Customizing the series appearance

Next, customize the series appearance by specifying the column color.

```xml
<model:ColumnSeriesExt Fill="#B8D86D">

</model:ColumnSeriesExt>
```

### Customize the data label appearance

To improve readability, we can activate the chart data labels using the [ShowDataLabels](https://help.syncfusion.com/cr/maui/Syncfusion.Maui.Charts.ChartSeries.html#Syncfusion_Maui_Charts_ChartSeries_ShowDataLabels "ShowDataLabels property of .NET MAUI Charts") property.

```xml
<model:ColumnSeriesExt ShowDataLabels="True">

 <chart:ColumnSeries.DataLabelSettings>
  <chart:CartesianDataLabelSettings LabelPlacement="Outer" UseSeriesPalette="False">
   <chart:CartesianDataLabelSettings.LabelStyle>
    <chart:ChartDataLabelStyle FontSize="{OnPlatform Android=11,iOS=11, Default=14}"
 FontFamily="AntaRegular" TextColor="Black"/>
   </chart:CartesianDataLabelSettings.LabelStyle>
  </chart:CartesianDataLabelSettings>
 </chart:ColumnSeries.DataLabelSettings>

</model:ColumnSeriesExt>
```

In the previous code example, the data labels display information about the water used during the production of the milk.

### Enhancing chart interactivity

To augment the informativeness of our column chart, we will integrate selection features and relevant information into the title view. The selection features allow us to highlight a specific data point when it is selected.

In this instance, we include images of a cow and the plants from which milk is made and their carbon emissions values in the title view and enable segment selection. Consequently, the view will show information about the selected segment.

```xml
<model:ColumnSeriesExt>

  <chart:ColumnSeries.SelectionBehavior>
    <chart:DataPointSelectionBehavior SelectionBrush="#9BD241" Type="SingleDeselect" SelectedIndex="{Binding SelectedIndex, Mode=TwoWay}"/>
  </chart:ColumnSeries.SelectionBehavior>

</model:ColumnSeriesExt>
```

In the following code example, we have created the **SourceImage** , **EmissionText** , and **SelectedIndex** properties to store the carbon emissions data.

```csharp
public class MilkSourceData : INotifyPropertyChanged
{

      private string sourceImage = "";
      public string SourceImage
      {
          get { return sourceImage; }
          set
          {
              if (sourceImage != value)
              {
                  sourceImage = value;
                  OnPropertyChanged(nameof(SourceImage));
              }
          }
      }

      private string emissionText = "";
      public string EmissionText
      {
          get { return emissionText; }
          set
          {
              if (emissionText != value)
              {
                  emissionText = value;
                  OnPropertyChanged(nameof(EmissionText));
              }
          }
      }

      private int selectedIndex;
      public int SelectedIndex
      {
          get { return selectedIndex; }
          set
          {
              selectedIndex = value;
              UpdateCountryAndCount();
              OnPropertyChanged(nameof(SelectedIndex));
          }
      }

      public MilkSourceData()
      {
          SelectedIndex = 1;
      }

      public event PropertyChangedEventHandler? PropertyChanged;
      protected virtual void OnPropertyChanged(string propertyName)
      {
          PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
      }

      private void UpdateCountryAndCount()
      {
          if (SelectedIndex >= 0 && SelectedIndex < Data?.Count)
          {
              SourceImage = Data[SelectedIndex].Source.ToLower() + ".png";
              EmissionText = Data[SelectedIndex].CO2Emission.ToString();
          }
      }
 }
```

After executing the previous code examples, the output will resemble the following GIF image. ![Visualizing the most sustainable milk data using .NET MAUI Column Chart](https://www.syncfusion.com/blogs/wp-content/uploads/2024/03/Visualizing-the-most-sustainable-milk-data-using-.NET-MAUI-Column-Chart.gif)

## GitHub reference

For more details, refer to [Visualizing the most sustainable types of milk using the .NET MAUI Column Chart GitHub demo](https://github.com/SyncfusionExamples/Creating-a-.NET-MAUI-Column-Chart-to-Visualize-which-Plant-Milk-is-the-Most-Sustainable "Visualizing the most sustainable types of milk using .NET MAUI Column Chart GitHub demo").

## Conclusion

Thank you for reading! In this blog, we have explored how to visualize the data on which milk is most sustainable based on various factors using the [Syncfusion .NET MAUI Column Chart](https://www.syncfusion.com/maui-controls/maui-cartesian-charts/chart-types/maui-column-chart "Syncfusion .NET MAUI Column Chart"). We encourage you to follow the steps outlined in this blog and share your feedback in the comments section below.

Current customers can download the newest version of Essential Studio from the [License and Downloads](https://www.syncfusion.com/account "Essential Studio License and Downloads page") page. If you are not a Syncfusion customer, try our [30-day free trial](https://www.syncfusion.com/downloads "Get the free 30-day evaluation of Essential Studio products") to check out our features.

If you require assistance, please don’t hesitate to contact us via our [support forum](https://www.syncfusion.com/forums "Syncfusion Support Forum"), [support portal](https://support.syncfusion.com/ "Syncfusion Support Portal"), or [feedback portal](https://www.syncfusion.com/feedback/maui "Syncfusion Feedback Portal"). We are always eager to help you!

## Related blogs

- [Load PDFs from Firebase Cloud Storage Using .NET MAUI PDF Viewer](https://www.syncfusion.com/blogs/post/load-firebase-cloud-pdfs-in-maui.aspx "Blog: Load PDFs from Firebase Cloud Storage Using .NET MAUI PDF Viewer")
- [Easily Manage Contacts in Your .NET MAUI App with SQLite and Perform CRUD Actions](https://www.syncfusion.com/blogs/post/manage-contact-maui-sqlite-crud.aspx "Blog: Easily Manage Contacts in Your .NET MAUI App with SQLite and Perform CRUD Actions")
- [Chart of the Week: Creating a .NET MAUI Bar Chart for the US’s Most-Traded Goods with China](https://www.syncfusion.com/blogs/post/maui-bar-chart-traded-goods-us.aspx "Blog: Chart of the Week: Creating a .NET MAUI Bar Chart for the US’s Most-Traded Goods with China")
- [Easily Replicate a Waiting List UI in .NET MAUI](https://www.syncfusion.com/blogs/post/waiting-list-ui-dotnet-maui.aspx "Blog: Easily Replicate a Waiting List UI in .NET MAUI")