Here is some code that appears to work for me to implement your own CommandColumnSeries, I stole a lot of it from the source for the ColumnSeries Sealed Class:
public class CommandColumnSeries : ColumnBarBaseSeries<ColumnDataPoint>
{
#region "ICommandSource"
[Localizability(LocalizationCategory.NeverLocalize), Category("Action"), Bindable(true)]
public ICommand Command
{
get
{
return (ICommand)base.GetValue(CommandProperty);
}
set
{
base.SetValue(CommandProperty, value);
}
}
[Bindable(true), Category("Action"), Localizability(LocalizationCategory.NeverLocalize)]
public object CommandParameter
{
get
{
return base.GetValue(CommandParameterProperty);
}
set
{
base.SetValue(CommandParameterProperty, value);
}
}
[Category("Action"), Bindable(true)]
public IInputElement CommandTarget
{
get
{
return (IInputElement)base.GetValue(CommandTargetProperty);
}
set
{
base.SetValue(CommandTargetProperty, value);
}
}
public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register("CommandParameter", typeof(object), typeof(CommandColumnSeries), new FrameworkPropertyMetadata(null));
public static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command", typeof(ICommand), typeof(CommandColumnSeries), new FrameworkPropertyMetadata(null));
public static readonly DependencyProperty CommandTargetProperty = DependencyProperty.Register("CommandTarget", typeof(IInputElement), typeof(CommandColumnSeries), new FrameworkPropertyMetadata(null));
#endregion
#region public IRangeAxis DependentRangeAxis
/// <summary>
/// Gets or sets the dependent range axis.
/// </summary>
public IRangeAxis DependentRangeAxis
{
get { return GetValue(DependentRangeAxisProperty) as IRangeAxis; }
set { SetValue(DependentRangeAxisProperty, value); }
}
/// <summary>
/// Identifies the DependentRangeAxis dependency property.
/// </summary>
[SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes", Justification = "This member is necessary because the base classes need to share this dependency property.")]
public static readonly DependencyProperty DependentRangeAxisProperty =
DependencyProperty.Register(
"DependentRangeAxis",
typeof(IRangeAxis),
typeof(ColumnSeries),
new PropertyMetadata(null, OnDependentRangeAxisPropertyChanged));
/// <summary>
/// DependentRangeAxisProperty property changed handler.
/// </summary>
/// <param name="d">ColumnBarBaseSeries that changed its DependentRangeAxis.</param>
/// <param name="e">Event arguments.</param>
private static void OnDependentRangeAxisPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
CommandColumnSeries source = (CommandColumnSeries)d;
IRangeAxis newValue = (IRangeAxis)e.NewValue;
source.OnDependentRangeAxisPropertyChanged(newValue);
}
/// <summary>
/// DependentRangeAxisProperty property changed handler.
/// </summary>
/// <param name="newValue">New value.</param>
private void OnDependentRangeAxisPropertyChanged(IRangeAxis newValue)
{
this.InternalDependentAxis = (IAxis)newValue;
}
#endregion public IRangeAxis DependentRangeAxis
#region public IAxis IndependentAxis
/// <summary>
/// Gets or sets the independent category axis.
/// </summary>
public IAxis IndependentAxis
{
get { return GetValue(IndependentAxisProperty) as IAxis; }
set { SetValue(IndependentAxisProperty, value); }
}
/// <summary>
/// Identifies the IndependentAxis dependency property.
/// </summary>
[SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes", Justification = "This member is necessary because the base classes need to share this dependency property.")]
public static readonly DependencyProperty IndependentAxisProperty =
DependencyProperty.Register(
"IndependentAxis",
typeof(IAxis),
typeof(ColumnSeries),
new PropertyMetadata(null, OnIndependentAxisPropertyChanged));
/// <summary>
/// IndependentAxisProperty property changed handler.
/// </summary>
/// <param name="d">ColumnBarBaseSeries that changed its IndependentAxis.</param>
/// <param name="e">Event arguments.</param>
private static void OnIndependentAxisPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
CommandColumnSeries source = (CommandColumnSeries)d;
IAxis newValue = (IAxis)e.NewValue;
source.OnIndependentAxisPropertyChanged(newValue);
}
/// <summary>
/// IndependentAxisProperty property changed handler.
/// </summary>
/// <param name="newValue">New value.</param>
private void OnIndependentAxisPropertyChanged(IAxis newValue)
{
this.InternalIndependentAxis = (IAxis)newValue;
}
#endregion public IAxis IndependentAxis
public CommandColumnSeries()
{
this.SelectionChanged += new SelectionChangedEventHandler(CommandColumnSeries_SelectionChanged);
}
private void CommandColumnSeries_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
if (Command != null)
{
RoutedCommand routedCommand = Command as RoutedCommand;
CommandParameter = e.Source;
if (routedCommand != null)
{
routedCommand.Execute(CommandParameter, CommandTarget);
}
else
{
Command.Execute(CommandParameter);
}
}
}
protected override void GetAxes(DataPoint firstDataPoint)
{
// Taken from the source of the ColumnSeries sealed class.
GetAxes(
firstDataPoint,
(axis) => axis.Orientation == AxisOrientation.X,
() => new CategoryAxis { Orientation = AxisOrientation.X },
(axis) =>
{
IRangeAxis rangeAxis = axis as IRangeAxis;
return rangeAxis != null && rangeAxis.Origin != null && axis.Orientation == AxisOrientation.Y;
},
() =>
{
IRangeAxis rangeAxis = CreateRangeAxisFromData(firstDataPoint.DependentValue);
rangeAxis.Orientation = AxisOrientation.Y;
if (rangeAxis == null || rangeAxis.Origin == null)
{
throw new InvalidOperationException("No Suitable Axes found for plotting range axis.");
}
DisplayAxis axis = rangeAxis as DisplayAxis;
if (axis != null)
{
axis.ShowGridLines = true;
}
return rangeAxis;
});
}
protected override void UpdateDataPoint(DataPoint dataPoint)
{
// This code taken from the ColumnSeries sealed class.
if (SeriesHost == null )//|| PlotArea == null)
{
return;
}
object category = dataPoint.ActualIndependentValue ?? (IndexOf<DataPoint>(this.ActiveDataPoints, dataPoint) + 1);
Range<UnitValue> coordinateRange = GetCategoryRange(category);
if (!coordinateRange.HasData)
{
return;
}
else if (coordinateRange.Maximum.Unit != Unit.Pixels || coordinateRange.Minimum.Unit != Unit.Pixels)
{
throw new InvalidOperationException("This Series Does Not Support Radial Axes");
}
double minimum = (double)coordinateRange.Minimum.Value;
double maximum = (double)coordinateRange.Maximum.Value;
double plotAreaHeight = ActualDependentRangeAxis.GetPlotAreaCoordinate(ActualDependentRangeAxis.Range.Maximum).Value.Value;
IEnumerable<CommandColumnSeries> columnSeries = SeriesHost.Series.OfType<CommandColumnSeries>().Where(series => series.ActualIndependentAxis == ActualIndependentAxis);
int numberOfSeries = columnSeries.Count();
double coordinateRangeWidth = (maximum - minimum);
double segmentWidth = coordinateRangeWidth * 0.8;
double columnWidth = segmentWidth / numberOfSeries;
int seriesIndex = IndexOf<CommandColumnSeries>(columnSeries, this);
double dataPointY = ActualDependentRangeAxis.GetPlotAreaCoordinate(ToDouble(dataPoint.ActualDependentValue)).Value.Value;
double zeroPointY = ActualDependentRangeAxis.GetPlotAreaCoordinate(ActualDependentRangeAxis.Origin).Value.Value;
double offset = seriesIndex * Math.Round(columnWidth) + coordinateRangeWidth * 0.1;
double dataPointX = minimum + offset;
if (GetIsDataPointGrouped(category))
{
// Multiple DataPoints share this category; offset and overlap them appropriately
IGrouping<object, DataPoint> categoryGrouping = GetDataPointGroup(category);
int index = GroupIndexOf(categoryGrouping, dataPoint);
dataPointX += (index * (columnWidth * 0.2)) / (categoryGrouping.Count() - 1);
columnWidth *= 0.8;
Canvas.SetZIndex(dataPoint, -index);
}
if (CanGraph(dataPointY) && CanGraph(dataPointX) && CanGraph(zeroPointY))
{
double left = Math.Round(dataPointX);
double width = Math.Round(columnWidth);
double top = Math.Round(plotAreaHeight - Math.Max(dataPointY, zeroPointY) + 0.5);
double bottom = Math.Round(plotAreaHeight - Math.Min(dataPointY, zeroPointY) + 0.5);
double height = bottom - top + 1;
Canvas.SetLeft(dataPoint, left);
Canvas.SetTop(dataPoint, top);
dataPoint.Width = width;
dataPoint.Height = height;
}
}
private static int IndexOf<T>(IEnumerable<T> collection, T target)
{
int i = 0;
foreach (var obj in collection)
{
if (obj.Equals(target))
return i;
i++;
}
return -1;
}
private static int GroupIndexOf(IGrouping<object, DataPoint> group, DataPoint point)
{
int i = 0;
foreach (var pt in group)
{
if (pt == point)
return i;
i++;
}
return -1;
}
/// <summary>
/// Returns a value indicating whether this value can be graphed on a
/// linear axis.
/// </summary>
/// <param name="value">The value to evaluate.</param>
/// <returns>A value indicating whether this value can be graphed on a
/// linear axis.</returns>
private static bool CanGraph(double value)
{
return !double.IsNaN(value) && !double.IsNegativeInfinity(value) && !double.IsPositiveInfinity(value) && !double.IsInfinity(value);
}
/// <summary>
/// Converts an object into a double.
/// </summary>
/// <param name="value">The value to convert to a double.</param>
/// <returns>The converted double value.</returns>
private static double ToDouble(object value)
{
return Convert.ToDouble(value, CultureInfo.InvariantCulture);
}
}