2009-07-06 5 views
1

Ich brauche einen Befehl angeben zu können, wenn das Selection-Ereignis ausgelöst laufen. Ich kann bereits die ICommandSource-Schnittstelle implementieren. Was ich wissen muss, ist, wie ich einfach einen Befehl zu der Spaltenfolge hinzufügen kann, um das SelectionChanged-Ereignis zu behandeln.Wie kann ich einen kommandierbaren Column in dem WPF-Toolkit Chart Control implementieren

Wenn ich von der ColumnBarBaseSeries < ...> Basisklasse erben, muss ich GetAxes() und UpdateDatePoint() überschreiben, die ich nicht sicher bin, wie zu implementieren.

Antwort

2

können Sie angebracht Verhalten verwenden, dieses Problem zu lösen.

Erstellen Sie ein SelectionChangedBehaviour, das ein selectionChanged-Ereignis an das Element bindet, mit dem Sie das Verhalten verknüpfen, dann können Sie jedes ICommand an dieses Verhalten binden.

Weitere Informationen über angebracht Verhalten -

Hoffnung, die hier

+0

Dies ist eine viel bessere Lösung als die, die ich unten geschrieben. Ich wünschte, ich wüsste davon, bevor ich 6 Stunden lang den ColumnSeries Quellcode in eine neue Klasse kopiert habe. – Jacob

+0

Yup angefügte Verhaltensweisen sind großartig. Eine Sache, die ich bei der WPF-Entwicklung bemerkt habe ... Sie sollten in der Lage sein, alles UI-spezifische von XAML mit Triggern, DPs und angehängten Verhaltensweisen usw. zu tun. Wenn Sie sich mit Code auf dem Codebehind hacken, dann gibt es mit Sicherheit einen besseren Weg. Der einzige Code-Behind, den ich habe, sind UI-spezifische Kalkulationen, die zur Laufzeit ausgeführt werden müssen. –

0

hilft ist ein Code, der für mich scheint zu funktionieren zu implementieren Ihre eigene CommandColumnSeri es, stahl ich eine Menge davon von der Quelle für die Column Klasse Sealed:

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

Hier einiger Code ist ein angeschlossenes Verhalten zu einem Column für einen Befehl Selection hinzuzufügen.

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

} 

Und in der XAML die Eigenschaft anbringt:

<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>