wpfgraphwpftoolkitchartssilverlight-toolkit

Draw a column graph with no space between columns


I am using the WPF toolkit, and am trying to render a graph that looks like a histogram. In particular, I want each column to be right up against each other column. There should be no gaps between columns.

There are a number of components that you apply when creating a column graph. (See example XAML below). Does anybody know if there is a property you can set on one of the elements which refers to the width of the white space between columns?

                <charting:Chart Height="600" Width="Auto" HorizontalAlignment="Stretch" Name="MyChart"
                    Title="Column Graph" LegendTitle="Legend">

                    <charting:ColumnSeries 
                        Name="theColumnSeries"
                        Title="Series A"
                        IndependentValueBinding="{Binding Path=Name}"                
                        DependentValueBinding="{Binding Path=Population}"
                        Margin="0"
                        >
                    </charting:ColumnSeries>

                    <charting:Chart.Axes>
                        <charting:LinearAxis 
                            Orientation="Y" 
                            Minimum="200000" 
                            Maximum="2500000" 
                            ShowGridLines="True" />
                        <charting:CategoryAxis
                            Name="chartCategoryAxis"
                            />
                    </charting:Chart.Axes>
                </charting:Chart>

Solution

  • In the absence of magically-appearing answers, I downloaded the wpftoolkit code from codeplex.

    By reading the code, I can see in the method ColumnSeries.UpdateDataPoint, there is this line of code:

        double segmentWidth = coordinateRangeWidth * 0.8;
    

    So that's a pretty definitive "no", you cannot change the gap in between columns by setting a public property.

    The solution which I'm going to try is to write a new class that inherits from ColumnSeries, and overriding UpdateDataPoint.


    Later Edit

    OK, I got it to work. In case anyone's interested, I've attached the full code for the HistogramSeries class.

    public class HistogramSeries : ColumnSeries, ISeries
    {
        protected override void UpdateDataPoint(DataPoint dataPoint)
        {
            // That set the height and width.
            base.UpdateDataPoint(dataPoint);
            // Now we override the part about setting the width
            object category = dataPoint.ActualIndependentValue;
            var coordinateRange = GetCategoryRange(category);
            double minimum = (double)coordinateRange.Minimum.Value;
            double maximum = (double)coordinateRange.Maximum.Value;
            double coordinateRangeWidth = (maximum - minimum);
            const int WIDTH_MULTIPLIER = 1; // Harcoded to 0.8 in the parent. Could make this a dependency property
            double segmentWidth = coordinateRangeWidth * WIDTH_MULTIPLIER;
            var columnSeries = SeriesHost.Series.OfType<ColumnSeries>().Where(series => series.ActualIndependentAxis == ActualIndependentAxis);
            int numberOfSeries = columnSeries.Count();
            double columnWidth = segmentWidth / numberOfSeries;
            int seriesIndex = columnSeries.IndexOf(this);
            double offset = seriesIndex * Math.Round(columnWidth) + coordinateRangeWidth * 0.1;
            double dataPointX = minimum + offset;
            double left = Math.Round(dataPointX);
            double width = Math.Round(columnWidth);
            Canvas.SetLeft(dataPoint, left);
            dataPoint.Width = width;
        }
        #region ISeries Members
        System.Collections.ObjectModel.ObservableCollection<object> ISeries.LegendItems
        {
            get { return base.LegendItems; }
        }
        #endregion
        #region IRequireSeriesHost Members
        ISeriesHost IRequireSeriesHost.SeriesHost
        {
            get { return base.SeriesHost;}
            set { base.SeriesHost = value; }
        }
        #endregion
    }
    // Copied from the DataVisualization library
    // (It was an internal class)
    static class MyEnumerableFunctions
    {
        public static int IndexOf(this IEnumerable that, object value)
        {
            int index = 0;
            foreach (object item in that)
            {
                if (object.ReferenceEquals(value, item) || value.Equals(item))
                {
                    return index;
                }
                index++;
            }
            return -1;
        }
    }