Mangiare Senza Glutine disponibile su App Store

Per altre informazioni scrivi a fabriziocaldarelli@negusweb.it

Ring Chart in WPF CSharp WinRT

Da Programmazione Software.

Il Ring Chart è il classico grafico a forma di ciambella, cioè dove è evidenziata l'area tra due circonferenze concentriche con raggi differenti.

Il pacchetto con l'esempio è costituito fondamentalmente da 2 files:

Main.xaml: contiene semplicemente l'oggetto RingChart e nell'initialize il popolamento dell'oggetto stesso, attraverso 2 modalità; la prima indiretta cioè attraverso l'assegnazione di un valore all'area (diciamo che è quello più umano) e poi quello diretto dove si vanno ad esplicitare l'angolo iniziale e finale.

Il controllo è personalizzabile attraverso il colore di ciascuna area definita, il colore e l'eventuale grandezza del bordo.

RingChart.xaml

<UserControl
    x:Class="Negusweb.Controls.RingChart"
    DataContext="{Binding  RelativeSource={RelativeSource Self}}"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:RingChart"
    xmlns:winrtToolkit="using:WinRTXamlToolkit.Controls"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300"
    d:DesignWidth="400"
    Name="ucRingChart"
    >
    <Grid>
        <ItemsControl ItemsSource="{Binding ChartItemsSource}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <Grid />
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <winrtToolkit:RingSlice
                    Fill="{Binding Fill}"
                    Stroke="{Binding Stroke}"
                    StrokeThickness="{Binding StrokeThickness}"
                    InnerRadius="{Binding Path=DataContext.InnerRadius,ElementName=ucRingChart}"
                    Radius="{Binding Path=DataContext.Radius,ElementName=ucRingChart}"
                    StartAngle="{Binding StartAngle}"
                    EndAngle="{Binding EndAngle}" />
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </Grid>
</UserControl>



RingChart.xaml

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
 
// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236
 
namespace Negusweb.Controls
{
    public sealed partial class RingChart : UserControl
    {
        public class RingChartItem
        {
            public double StartAngle { get; set; }
            public double EndAngle { get; set; }
            public Brush Fill { get; set; }
            public Brush Stroke { get; set; }
            public double StrokeThickness { get; set; }
 
            public RingChartItem(double startAngleInput, double endAngleInput, Brush fillInput)
            {
                this.StartAngle = startAngleInput;
                this.EndAngle = endAngleInput;
                this.Fill = fillInput;
                this.Stroke = null;
                this.StrokeThickness = 0;
            }
 
            public static RingChartItem CreaDaValore(double valore, double totale, Brush fillInput)
            {
                double temp = valore * 360 / totale;
 
                RingChartItem rci = new RingChartItem(0, temp, fillInput);
                return rci;
            }
        }
 
        #region ChartItemsSource
        /// <summary>
        /// The start angle property.
        /// </summary>
        public static readonly DependencyProperty ChartItemsSourceProperty =
            DependencyProperty.Register(
                "ChartItemsSource",
                typeof(List<RingChartItem>),
                typeof(RingChart),
                new PropertyMetadata(
                    null,
                    OnChartItemsSourceChanged));
 
        /// <summary>
        /// Gets or sets the start angle.
        /// </summary>
        /// <value>
        /// The start angle.
        /// </value>
        public List<RingChartItem> ChartItemsSource
        {
            get
            {
                return (List<RingChartItem>)GetValue(ChartItemsSourceProperty);
            }
            set
            {
                SetValue(ChartItemsSourceProperty, value);
            }
        }
 
        private static void OnChartItemsSourceChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            var target = (RingChart)sender;
            var oldStartAngle = (List<RingChartItem>)e.OldValue;
            var newStartAngle = (List<RingChartItem>)e.NewValue;
            target.OnChartItemsSourceChanged(oldStartAngle, newStartAngle);
        }
 
        private void OnChartItemsSourceChanged(List<RingChartItem> oldStartAngle, List<RingChartItem> newStartAngle)
        {
            //UpdatePath();
            int a = 0;
        }
        #endregion
 
        #region Radius
        /// <summary>
        /// The radius property
        /// </summary>
        public static readonly DependencyProperty RadiusProperty =
            DependencyProperty.Register(
                "Radius",
                typeof(double),
                typeof(RingChart),
                new PropertyMetadata(
                    0d,
                    OnRadiusChanged));
 
        /// <summary>
        /// Gets or sets the outer radius.
        /// </summary>
        /// <value>
        /// The outer radius.
        /// </value>
        public double Radius
        {
            get { return (double)GetValue(RadiusProperty); }
            set { SetValue(RadiusProperty, value); }
        }
 
        private static void OnRadiusChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            var target = (RingChart)sender;
            var oldRadius = (double)e.OldValue;
            var newRadius = (double)e.NewValue;
            target.OnRadiusChanged(oldRadius, newRadius);
        }
 
        private void OnRadiusChanged(double oldRadius, double newRadius)
        {
            this.Width = this.Height = 2 * Radius;
            //UpdatePath();
        }
        #endregion
 
        #region InnerRadius
        /// <summary>
        /// The inner radius property
        /// </summary>
        public static readonly DependencyProperty InnerRadiusProperty =
            DependencyProperty.Register(
                "InnerRadius",
                typeof(double),
                typeof(RingChart),
                new PropertyMetadata(
                    0d,
                    OnInnerRadiusChanged));
 
        /// <summary>
        /// Gets or sets the inner radius.
        /// </summary>
        /// <value>
        /// The inner radius.
        /// </value>
        public double InnerRadius
        {
            get { return (double)GetValue(InnerRadiusProperty); }
            set { SetValue(InnerRadiusProperty, value); }
        }
 
        private static void OnInnerRadiusChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            var target = (RingChart)sender;
            var oldInnerRadius = (double)e.OldValue;
            var newInnerRadius = (double)e.NewValue;
            target.OnInnerRadiusChanged(oldInnerRadius, newInnerRadius);
        }
 
        private void OnInnerRadiusChanged(double oldInnerRadius, double newInnerRadius)
        {
            if (newInnerRadius < 0)
            {
                throw new ArgumentException("InnerRadius can't be a negative value.", "InnerRadius");
            }
 
            //UpdatePath();
        }
        #endregion
 
        #region EmptyBrush
        /// <summary>
        /// The inner radius property
        /// </summary>
        public static readonly DependencyProperty EmptyBrushProperty =
            DependencyProperty.Register(
                "EmptyBrush",
                typeof(Brush),
                typeof(RingChart),
                new PropertyMetadata(
                    new SolidColorBrush(Color.FromArgb(0xFF, 0x77, 0x77, 0x77)),
                    OnEmptyBrushChanged));
 
        /// <summary>
        /// Gets or sets the inner radius.
        /// </summary>
        /// <value>
        /// The inner radius.
        /// </value>
        public Brush EmptyBrush
        {
            get { return (Brush)GetValue(EmptyBrushProperty); }
            set { SetValue(EmptyBrushProperty, value); }
        }
 
        private static void OnEmptyBrushChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            var target = (RingChart)sender;
            var oldInnerRadius = (Brush)e.OldValue;
            var newInnerRadius = (Brush)e.NewValue;
            target.OnEmptyBrushChanged(oldInnerRadius, newInnerRadius);
        }
 
        private void OnEmptyBrushChanged(Brush oldInnerRadius, Brush newInnerRadius)
        {
            //UpdatePath();
        }
        #endregion
 
        #region IsEmptyBrushDrawn
        /// <summary>
        /// The inner radius property
        /// </summary>
        public static readonly DependencyProperty IsEmptyBrushDrawnProperty =
            DependencyProperty.Register(
                "IsEmptyBrushDrawn",
                typeof(bool),
                typeof(RingChart),
                new PropertyMetadata(
                    true,
                    OnEmptyBrushDrawnChanged));
 
        /// <summary>
        /// Gets or sets the inner radius.
        /// </summary>
        /// <value>
        /// The inner radius.
        /// </value>
        public bool IsEmptyBrushDrawn
        {
            get { return (bool)GetValue(IsEmptyBrushDrawnProperty); }
            set { SetValue(IsEmptyBrushDrawnProperty, value); }
        }
 
        private static void OnEmptyBrushDrawnChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            var target = (RingChart)sender;
            var oldInnerRadius = (bool)e.OldValue;
            var newInnerRadius = (bool)e.NewValue;
            target.OnEmptyBrushDrawnChanged(oldInnerRadius, newInnerRadius);
        }
 
        private void OnEmptyBrushDrawnChanged(bool oldInnerRadius, bool newInnerRadius)
        {
            //UpdatePath();
        }
        #endregion
 
        public double? StartAngle { get; set; }
 
        public RingChart()
        {
            this.InitializeComponent();
        }
 
        public void AggiornaDaListaItemValori(List<RingChartItem> lstInput)
        {
            double dx = (StartAngle != null) ? StartAngle.Value : 0;
            double angoloIniziale = dx;
            double angoloFinale = 0;
 
            List<RingChartItem> lstOut = new List<RingChartItem>();
            for (int k = 0; k < lstInput.Count; k++)
            {
                RingChartItem rci = lstInput[k];
 
                if ((k == 0) && (angoloIniziale == 0))
                {
                    angoloIniziale = rci.StartAngle;
                }
 
                angoloFinale = angoloIniziale + rci.EndAngle;
 
                lstOut.Add(new RingChartItem(angoloIniziale, angoloFinale, rci.Fill));
 
                angoloIniziale = angoloFinale;
 
            }
            if (IsEmptyBrushDrawn)
            {
                if (angoloIniziale < 360)
                {
                    angoloFinale = 360;
                    lstOut.Add(new RingChartItem(angoloIniziale, angoloFinale, EmptyBrush));
                }
            }
 
            this.ChartItemsSource = lstOut;
        }
    }
}



Il risultato è quello che segue
Ringchart screenshot.jpg

Allegati