How to bind own color from ViewModel? (PieSeries)

Sep 22, 2014 at 12:30 AM
Edited Sep 22, 2014 at 11:02 AM
This is solution, not a question. Only for PieSeries.

My ViewModel looks like:
    public class PartViewModel : ViewModelBase
    {
        private Part _part;
        /// <summary>
        /// Initializes a new instance of the PartViewModel class.
        /// </summary>
        public PartViewModel(Part part)
        {
            _part = part;
        }

        #region Properties

        public string Name
        {
            get
            {
                return _part.Name;
            }
            set
            {
                if (_part.Name != value)
                {
                    _part.Name = value;
                    RaisePropertyChanged("Name");
                }
            }
        }

        public float Value
        {
            get
            {
                return _part.Value;
            }
            set
            {
                if (_part.Value != value)
                {
                    _part.Value = value;
                    RaisePropertyChanged("Value");
                }
            }
        }

        public string Color
        {
            get
            {
                return _part.Color;
            }
            set
            {
                if (_part.Color != value)
                {
                    _part.Color = value;
                    RaisePropertyChanged("Color");
                }
            }
        }
...
MainView.xaml
        <charting:Chart>
            <charting:PieSeries ItemsSource="{Binding Parts}" IndependentValuePath="Name" DependentValuePath="Value" SelectedItem="{Binding SelectedPart, Mode=TwoWay}" DataPointColorPath="Color">
            </charting:PieSeries>
        </charting:Chart>
Should download the source code and make changes to the WinRT toolkit:

\WinRTXamlToolkit.Controls.DataVisualization\Charting\DataPoint\DataPoint.cs:
Insert:
        /// <summary>
        /// Called when the color of the data point is changed.
        /// </summary>
        internal event RoutedPropertyChangedEventHandler<object> DataPointColorChanged;

        #region public Brush DataPointColor
        /// <summary>
        /// Gets or sets the DataPointColor.
        /// </summary>
        public Brush DataPointColor
        {
            get { return (Brush)GetValue(DataPointColorProperty); }
            set { SetValue(DataPointColorProperty, value); }
        }

        /// <summary>
        /// Identifies the DataPointColor dependency property.
        /// </summary>
        public static readonly DependencyProperty DataPointColorProperty =
            DependencyProperty.Register(
                "DataPointColor",
                typeof(Brush),
                typeof(DataPoint),
                new PropertyMetadata(null, OnDataPointColorPropertyChanged));

        /// <summary>
        /// Called when the DataPointColor property changes.
        /// </summary>
        /// <param name="d">Control that changed its DataPointColor.</param>
        /// <param name="e">Event arguments.</param>
        private static void OnDataPointColorPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DataPoint source = (DataPoint)d;
            object oldValue = e.OldValue;
            object newValue = e.NewValue;
            source.OnDataPointColorPropertyChanged(oldValue, newValue);
        }

        /// <summary>
        /// Called when the DataPointColor property changes.
        /// </summary>
        /// <param name="oldValue">The old value.</param>
        /// <param name="newValue">The new value.</param>
        protected virtual void OnDataPointColorPropertyChanged(object oldValue, object newValue)
        {
            RoutedPropertyChangedEventHandler<object> handler = this.DataPointColorChanged;
            if (handler != null)
            {
                handler(this, new RoutedPropertyChangedEventArgs<object>(oldValue, newValue));
            }
            this.SetValue(DataPoint.BackgroundProperty, DataPointColor);
        }
        #endregion public object DataPointColor
\WinRTXamlToolkit.Controls.DataVisualization\Charting\Series\DataPointSeries.cs:
Insert:
        /// <summary>
        /// The binding used to identify the independent value binding.
        /// </summary>
        private Binding _dataPointColorBinding;

        /// <summary>
        /// Gets or sets the Binding to use for identifying the DataPoint color.
        /// </summary>
        public Binding DataPointColorBinding
        {
            get
            {
                return _dataPointColorBinding;
            }
            set
            {
                if (_dataPointColorBinding != value)
                {
                    _dataPointColorBinding = value;
                    Refresh();
                }
            }
        }

        /// <summary>
        /// Gets or sets the Binding Path to use for identifying the DataPoint color.
        /// </summary>
        public string DataPointColorPath
        {
            get
            {
                return (null != DataPointColorBinding) ? DataPointColorBinding.Path.Path : null;
            }
            set
            {
                if (null == value)
                {
                    DataPointColorBinding = null;
                }
                else
                {
                    DataPointColorBinding = new Binding { Path = new PropertyPath(value) };
                }
            }
        }
\WinRTXamlToolkit.Controls.DataVisualization\Charting\Series\DataPointSeries.cs:
Edit (+++):
        protected virtual void PrepareDataPoint(DataPoint dataPoint, object dataContext)
        {
            ...

            +++if (DataPointColorBinding != null)
            +++{
                +++dataPoint.SetBinding(DataPoint.DataPointColorProperty, DataPointColorBinding);
            +++}
        }
\WinRTXamlToolkit.Controls.DataVisualization\Charting\Series\PieSeries.cs:
Edit (+++):
        /// <summary>
        /// Creates a legend item from a data point.
        /// </summary>
        /// <param name="dataPoint">The data point to use to create the legend item.</param>
        /// <param name="index">The 1-based index of the Control.</param>
        /// <returns>The series host legend item.</returns>
        protected virtual LegendItem CreatePieLegendItem(DataPoint dataPoint, int index)
        {
            .....
            legendDataPoint.SetBinding(DataPoint.StyleProperty, new Binding { Path = new PropertyPath(PieDataPoint.ActualDataPointStyleName), Source = dataPoint });
            
            +++if (dataPoint.DataPointColor != null) legendDataPoint.SetValue(DataPoint.BackgroundProperty, dataPoint.DataPointColor);
            
            legendItem.DataContext = legendDataPoint;
            return legendItem;
        }
\WinRTXamlToolkit.Controls.DataVisualization\Charting\Series\PieSeries.cs:
Insert:
        /// <summary>
        /// Updates the data point when the pie data point's color is 
        /// changed.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="args">Information about the event.</param>
        private void OnDataPointColorChanged(object sender, RoutedPropertyChangedEventArgs<object> args)
        {
            DataPoint dataPoint = sender as DataPoint;
            int indexOfPoint = this.ActiveDataPoints.IndexOf(dataPoint);
            if (indexOfPoint >= 0 && this.LegendItems.Count > indexOfPoint)
            {
                DataPoint legendDataPoint = (DataPoint)((LegendItem)this.LegendItems[indexOfPoint]).DataContext;
                legendDataPoint.SetValue(DataPoint.BackgroundProperty, dataPoint.DataPointColor);
            }
        }
\WinRTXamlToolkit.Controls.DataVisualization\Charting\Series\PieSeries.cs:
Edit (+++):
        /// <summary>
        /// Attach event handlers to a data point.
        /// </summary>
        /// <param name="dataPoint">The data point.</param>
        protected override void AttachEventHandlersToDataPoint(DataPoint dataPoint)
        {
            ...
            pieDataPoint.OffsetRatioChanged += OnPieDataPointOffsetRatioChanged;
            +++pieDataPoint.DataPointColorChanged += OnDataPointColorChanged;

            base.AttachEventHandlersToDataPoint(dataPoint);
        }

        /// <summary>
        /// Detaches event handlers from a data point.
        /// </summary>
        /// <param name="dataPoint">The data point.</param>
        protected override void DetachEventHandlersFromDataPoint(DataPoint dataPoint)
        {
            ...
            pieDataPoint.OffsetRatioChanged -= OnPieDataPointOffsetRatioChanged;
            +++pieDataPoint.DataPointColorChanged -= OnDataPointColorChanged;

            base.DetachEventHandlersFromDataPoint(dataPoint);
        }
Have a successful projects. Best regards. Denis Pujdak.
Marked as answer by ViDom on 9/21/2014 at 5:34 PM
Sep 22, 2014 at 10:58 AM
And also it's possible change MouseOver and Selection colors:

WinRTXamlToolkit.Controls.DataVisualization\Charting\DataPoint\PieDataPoint.xaml (Line 120):
Edit:
<Path
                            x:Name="SelectionHighlight"
                            Data="{TemplateBinding GeometrySelection}"
                            Fill="#4C000000"
                            StrokeMiterLimit="1"
                            Stroke="Black"
                            StrokeThickness="3"
                            IsHitTestVisible="False"
                            Opacity="0" />
                        <Path
                            x:Name="MouseOverHighlight"
                            Data="{TemplateBinding GeometryHighlight}"
                            Fill="#4CFFFFFF"
                            StrokeMiterLimit="1"
                            IsHitTestVisible="False"
                            Opacity="0" />
Marked as answer by ViDom on 9/22/2014 at 3:58 AM
Coordinator
Sep 22, 2014 at 9:46 PM
Thanks (dzięki). When I get the chance I'll check if it would make sense to add the code to the toolkit. You can already specify custom colors in XAML, but being able to get these from the bound data points easily feels like a nice addition.
Sep 22, 2014 at 9:58 PM
Ok. (bardzo proszę ;-)