2009-07-06 33 views
1

我需要能夠指定在SelectionChanged事件觸發時運行的命令。我已經知道如何實現ICommandSource接口;我需要知道的是我如何才能在列系列中添加命令來處理SelectionChanged事件。如何在WPF工具包的圖表控件中實現可命令的ColumnSeries

當我從ColumnBarBaseSeries <繼承...>基類,我必須覆蓋GetAxes()和UpdateDatePoint(),這我不知道如何實現。

回答

2

您可以使用附加行爲來解決此問題。

創建一個SelectionChangedBehaviour,將selectionChanged事件連接到要附加行爲的元素,然後您可以將任何ICommand綁定到該行爲。

更多關於附加的行爲 -

希望幫助

+0

這是一個比我下面貼了更好的解決方案。希望在我花6個小時將ColumnSeries源代碼複製到新課程之前,我知道它。 – Jacob 2009-07-06 15:11:12

0

這裏,似乎爲我工作落實一些代碼你自己的CommandColumnSeri ES,我偷了很多它的源密封類檢測ColumnSeries:

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); 
    } 


} 
1

下面是一些代碼到一個附加行爲添加到的ColumnSeries的命令的SelectionChanged。

public static class ColumnSeriesBehavior 
{ 
    private static DelegateCommand<object> SelectionChangedCommand;  

    public static DelegateCommand<object> GetSelectionChangedCommand(ColumnSeries cs) 
    { 
     return cs.GetValue(SelectionChangedCommandProperty) as DelegateCommand<object>; 
    } 

    public static void SetSelectionChangedCommand(ColumnSeries cs, DelegateCommand<object> value) 
    { 
     cs.SetValue(SelectionChangedCommandProperty, value); 
    } 

    // Using a DependencyProperty as the backing store for SelectionChangedCommand. This enables animation, styling, binding, etc... 
    public static readonly DependencyProperty SelectionChangedCommandProperty = 
     DependencyProperty.RegisterAttached("SelectionChangedCommand", typeof(DelegateCommand<object>), typeof(ColumnSeriesBehavior), new UIPropertyMetadata(null, OnSelectionChangedCommandChanged)); 

    private static void OnSelectionChangedCommandChanged(
     DependencyObject depObj, DependencyPropertyChangedEventArgs e) 
    { 
     ColumnSeries item = depObj as ColumnSeries; 
     if (item == null) 
     {     
      return; 
     } 
     if (e.NewValue is DelegateCommand<object> == false) 
     { 

      return; 
     } 

     SelectionChangedCommand = e.NewValue as DelegateCommand<object>; 
     item.SelectionChanged += new System.Windows.Controls.SelectionChangedEventHandler(Column_SelectionChanged); 
    } 

    private static void Column_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e) 
    { 
     if (SelectionChangedCommand != null) 
      SelectionChangedCommand.Execute(sender); 
    } 

} 

而在XAML附加屬性:

<chartingToolkit:Chart.Series> 
      <chartingToolkit:ColumnSeries 
       IsSelectionEnabled="True"           
       ItemsSource="{Binding YourItemSource}" 
       IndependentValueBinding="{Binding YourIndValue, Path=YourIndValuePath}" 
       DependentValueBinding="{Binding YourDepValue, Path=YourDepValuePath}"           
       > 
       <chartingToolkit:ColumnSeries.Style> 
        <Style> 
         <!-- Attaching the SelectionChangedCommand behavior --> 
         <Setter Property="local:ColumnSeriesBehavior.SelectionChangedCommand" 
           Value="{Binding YourDelegateCommand}"/> 
        </Style> 
       </chartingToolkit:ColumnSeries.Style> 
      </chartingToolkit:ColumnSeries> 
     </chartingToolkit:Chart.Series> 
相關問題