我正在创建一个DataVisualization.Chart类型的用户控件组件。现在,他接受4个范围限制(1个范围最小接受值和1个最大值,1个范围最小值警告值和1个最大警告范围值)。 到现在为止还挺好。有用。但我需要在LineSeries的末尾添加一个TextBlock(或标签,或TextBox,无论如何)。
这是我的实际LineSeries:
现在我需要做这样的事情:
即使结果不一样,我也需要在每个LineDataPoint的末尾放置一个标签或文本块。
修改1:
这就是我的项目列表的生成方式:
/// <summary>
/// Generate ItemsSource to use with chart component
/// </summary>
/// <returns>A observable collection items of ChartItems type</returns>
public ObservableCollection<ChartItems> GenerateActualValues()
{
var itemsSource = ItemsSource as IEnumerable;
if (itemsSource.IsNull())
return null;
// Get all values from ItemsSource to set Axis Y of Chart
List<Double> listAxisY = new List<Double>();
ObservableCollection<ChartItems> chartItems = new ObservableCollection<ChartItems>();
foreach (ChartItems itemSource in itemsSource)
{
listAxisY.Add(itemSource.ValueY);
chartItems.Add(new ChartItems { Name = itemSource.Name, ValueY = itemSource.ValueY, ValueXDouble = itemSource.ValueXDouble, ValueXDateTime = itemSource.ValueXDateTime, Color = itemSource.Color });
}
// Set minimum and maximum axis Y if automatic
if (AutomaticAxisY)
{
Double? maxValue;
Double? minValue;
if (listAxisY.Count > 0)
{
if (GetMaxLimitValue1(this) > listAxisY.Max())
maxValue = GetMaxLimitValue1(this);
else
maxValue = listAxisY.Max();
if (GetMinLimitValue1(this) < listAxisY.Min())
minValue = GetMinLimitValue1(this);
else
minValue = listAxisY.Min();
}
else
{
maxValue = GetMaxLimitValue1(this);
minValue = GetMinLimitValue1(this);
}
Double? increment = (maxValue - minValue) * 0.05;
MaximumAxisY = (maxValue + increment).ConvertNullDoubleToDouble();
MinimumAxisY = (minValue - increment).ConvertNullDoubleToDouble();
if (MaximumAxisY == MinimumAxisY)
{
MaximumAxisY += 1;
MinimumAxisY -= 1;
}
}
return chartItems;
}
基本上,它生成一个新的ItemsSource以在我的图表中使用。现在,要生成那些额外的行:
/// <summary>
/// Generate a ItemsSource using param option informed
/// </summary>
/// <param name="option">Min1, Max1, Min2, Max2 or Target Value</param>
/// <returns>Observable Collection of ChartItems</returns>
public ObservableCollection<ChartItems> GenerateLimitValues(String option)
{
var itemsSource = ItemsSource as IEnumerable;
if (itemsSource.IsNull())
return null;
Double? valueY = 0.0;
ObservableCollection<ChartItems> chartItems = new ObservableCollection<ChartItems>();
switch (option)
{
case "Min1":
valueY = GetMinLimitValue1(this);
break;
case "Max1":
valueY = GetMaxLimitValue1(this);
break;
case "Target":
valueY = GetTargetValue(this);
break;
case "Min2":
valueY = GetMinLimitValue2(this);
break;
case "Max2":
valueY = GetMaxLimitValue2(this);
break;
}
foreach (ChartItems itemSource in itemsSource)
chartItems.Add(new ChartItems { Name = itemSource.Name, ValueY = valueY.ConvertNullDoubleToDouble(), ValueXDouble = itemSource.ValueXDouble, ValueXDateTime = itemSource.ValueXDateTime });
return chartItems;
}
现在,这就是我的图表中所有工作都可以使用的地方:
/// <summary>
/// Generates series with values for chart
/// </summary>
public void RenderizeChart()
{
while (this.chartView.Series.Count() - 1 >= 0)
this.chartView.Series.Remove(this.chartView.Series[0]);
DataPointSeries lineSeriesActualValue = null;
DataPointSeries lineSeriesMaxValue1 = null;
DataPointSeries lineSeriesMinValue1 = null;
DataPointSeries lineSeriesMaxValue2 = null;
DataPointSeries lineSeriesMinValue2 = null;
DataPointSeries lineSeriesTarget = null;
if (!ChartTypeSelectedItem.IsNull())
switch ((ChartTypes)ChartTypeSelectedItem)
{
case ChartTypes.Bar:
this.chartView.Series.Add(new BarSeries());
lineSeriesActualValue = this.chartView.Series[0] as BarSeries;
break;
case ChartTypes.Columns:
this.chartView.Series.Add(new ColumnSeries());
lineSeriesActualValue = this.chartView.Series[0] as ColumnSeries;
lineSeriesActualValue.DataPointStyle = (Style)this.Resources["ColumnDataPointStyle"];
break;
case ChartTypes.Pie:
this.chartView.Series.Add(new PieSeries());
lineSeriesActualValue = this.chartView.Series[0] as PieSeries;
break;
case ChartTypes.Lines:
this.chartView.Series.Add(new LineSeries());
lineSeriesActualValue = this.chartView.Series[0] as LineSeries;
lineSeriesActualValue.Style = (Style)this.Resources["LineSeriesStyle"];
if (!ShowPoints)
{
// Brief explanation: if user wants to hide Data Points, it's necessary to get all Setters on
// LineDataPointStyle inside xaml, clear previous style and add new Setter.
// Otherwise, it will not work, will deny changes because its sealed.
Style style = (Style)this.Resources["LineDataPointStyle"];
List<Setter> setterList = new List<Setter>();
foreach (Setter setter in style.Setters)
setterList.Add(setter);
style = new Style();
foreach (var setter in setterList)
style.Setters.Add(setter);
style.Setters.Add(new Setter(LineSeries.TemplateProperty, null));
lineSeriesActualValue.DataPointStyle = style;
}
else
lineSeriesActualValue.DataPointStyle = (Style)this.Resources["LineDataPointStyle"];
break;
case ChartTypes.Area:
this.chartView.Series.Add(new AreaSeries());
lineSeriesActualValue = this.chartView.Series[0] as AreaSeries;
break;
default:
break;
}
if (!lineSeriesActualValue.IsNull())
{
lineSeriesActualValue.IsSelectionEnabled = true;
lineSeriesActualValue.DependentValuePath = FieldForDependentValue;
lineSeriesActualValue.IndependentValuePath = FieldForIndependentValue;
lineSeriesActualValue.ItemsSource = GenerateActualValues();
// Adding a max limit to chart
if (!ItemsSource.IsNull() && ((!GetMaxLimitValue1(this).IsNull()) && !GetMaxLimitValue1(this).Equals(0.0)))
{
this.chartView.Series.Add(new LineSeries());
lineSeriesMaxValue1 = this.chartView.Series[1] as LineSeries;
Style styleMaxLineSeries = new Style();
styleMaxLineSeries.Setters.Add(new Setter(LineSeries.BackgroundProperty, new SolidColorBrush(Color.FromArgb(255, 234, 178, 15))));
styleMaxLineSeries.Setters.Add(new Setter(LineSeries.TemplateProperty, null));
lineSeriesMaxValue1.DataPointStyle = styleMaxLineSeries;
lineSeriesMaxValue1.DependentValuePath = FieldForDependentValue;
lineSeriesMaxValue1.IndependentValuePath = FieldForIndependentValue;
lineSeriesMaxValue1.ItemsSource = GenerateLimitValues("Max1");
if (this.chartView.Series.Contains(lineSeriesMaxValue1))
this.chartView.Series.Remove(lineSeriesMaxValue1);
this.chartView.Series.Add(lineSeriesMaxValue1);
}
// Adding a min limit to chart
if (!ItemsSource.IsNull() && ((!GetMinLimitValue1(this).IsNull()) && !GetMinLimitValue1(this).Equals(0.0)))
{
this.chartView.Series.Add(new LineSeries());
lineSeriesMinValue1 = this.chartView.Series[2] as LineSeries;
Style styleMinLineSeries = new Style();
styleMinLineSeries.Setters.Add(new Setter(LineSeries.BackgroundProperty, new SolidColorBrush(Color.FromArgb(255, 234, 178, 15))));
styleMinLineSeries.Setters.Add(new Setter(LineSeries.TemplateProperty, null));
lineSeriesMinValue1.DataPointStyle = styleMinLineSeries;
lineSeriesMinValue1.DependentValuePath = FieldForDependentValue;
lineSeriesMinValue1.IndependentValuePath = FieldForIndependentValue;
lineSeriesMinValue1.ItemsSource = GenerateLimitValues("Min1");
if (this.chartView.Series.Contains(lineSeriesMinValue1))
this.chartView.Series.Remove(lineSeriesMinValue1);
this.chartView.Series.Add(lineSeriesMinValue1);
}
// Adding a target value to chart
if (!ItemsSource.IsNull() && ((!GetTargetValue(this).IsNull()) && !GetTargetValue(this).Equals(0.0)))
{
this.chartView.Series.Add(new LineSeries());
lineSeriesTarget = this.chartView.Series[3] as LineSeries;
Style styleTargetLineSeries = new Style();
styleTargetLineSeries.Setters.Add(new Setter(LineSeries.BackgroundProperty, Brushes.Gray));
styleTargetLineSeries.Setters.Add(new Setter(LineSeries.TemplateProperty, null));
lineSeriesTarget.DataPointStyle = styleTargetLineSeries;
lineSeriesTarget.DependentValuePath = FieldForDependentValue;
lineSeriesTarget.IndependentValuePath = FieldForIndependentValue;
lineSeriesTarget.ItemsSource = GenerateLimitValues("Target");
if (this.chartView.Series.Contains(lineSeriesTarget))
this.chartView.Series.Remove(lineSeriesTarget);
this.chartView.Series.Add(lineSeriesTarget);
}
// Adding a max limit to chart
if (!ItemsSource.IsNull() && ((!GetMaxLimitValue2(this).IsNull()) && !GetMaxLimitValue2(this).Equals(0.0)))
{
this.chartView.Series.Add(new LineSeries());
lineSeriesMaxValue2 = this.chartView.Series[4] as LineSeries;
Style styleMaxLineSeries = new Style();
styleMaxLineSeries.Setters.Add(new Setter(LineSeries.BackgroundProperty, new SolidColorBrush(Color.FromArgb(255, 255, 0, 0))));
styleMaxLineSeries.Setters.Add(new Setter(LineSeries.TemplateProperty, null));
lineSeriesMaxValue2.DataPointStyle = styleMaxLineSeries;
lineSeriesMaxValue2.DependentValuePath = FieldForDependentValue;
lineSeriesMaxValue2.IndependentValuePath = FieldForIndependentValue;
lineSeriesMaxValue2.ItemsSource = GenerateLimitValues("Max2");
if (this.chartView.Series.Contains(lineSeriesMaxValue2))
this.chartView.Series.Remove(lineSeriesMaxValue2);
this.chartView.Series.Add(lineSeriesMaxValue2);
}
// Adding a min limit to chart
if (!ItemsSource.IsNull() && ((!GetMinLimitValue2(this).IsNull()) && !GetMinLimitValue2(this).Equals(0.0)))
{
this.chartView.Series.Add(new LineSeries());
lineSeriesMinValue2 = this.chartView.Series[5] as LineSeries;
Style styleMinLineSeries = new Style();
styleMinLineSeries.Setters.Add(new Setter(LineSeries.BackgroundProperty, new SolidColorBrush(Color.FromArgb(255, 255, 0, 0))));
styleMinLineSeries.Setters.Add(new Setter(LineSeries.TemplateProperty, null));
lineSeriesMinValue2.DataPointStyle = styleMinLineSeries;
lineSeriesMinValue2.DependentValuePath = FieldForDependentValue;
lineSeriesMinValue2.IndependentValuePath = FieldForIndependentValue;
lineSeriesMinValue2.ItemsSource = GenerateLimitValues("Min2");
if (this.chartView.Series.Contains(lineSeriesMinValue2))
this.chartView.Series.Remove(lineSeriesMinValue2);
this.chartView.Series.Add(lineSeriesMinValue2);
}
// Configure axis
if (ItemsSource.IsNull() || (((IList)ItemsSource).Count == 0))
{
foreach (var actualAxis in this.chartView.ActualAxes)
if (actualAxis.Orientation.Equals(AxisOrientation.Y))
{
(actualAxis as LinearAxis).Maximum = null;
(actualAxis as LinearAxis).Minimum = null;
(actualAxis as LinearAxis).ShowGridLines = ShowGridLinesY;
(actualAxis as LinearAxis).Visibility = Visibility.Collapsed;
}
else if (actualAxis.Orientation.Equals(AxisOrientation.X))
{
if (actualAxis is DateTimeAxis)
{
if (!FieldForIndependentValue.IsNullOrEmpty() && FieldForIndependentValue.Contains("DateTime"))
{
(actualAxis as DateTimeAxis).Maximum = null;
(actualAxis as DateTimeAxis).Minimum = null;
(actualAxis as DateTimeAxis).Visibility = Visibility.Collapsed;
}
else
(actualAxis as DateTimeAxis).Visibility = Visibility.Collapsed;
}
else
{
if (!FieldForIndependentValue.IsNullOrEmpty() && FieldForIndependentValue.Contains("Double"))
{
(actualAxis as LinearAxis).Maximum = null;
(actualAxis as LinearAxis).Minimum = null;
(actualAxis as LinearAxis).Visibility = Visibility.Collapsed;
(actualAxis as LinearAxis).ShowGridLines = ShowGridLinesX;
}
else
(actualAxis as LinearAxis).Visibility = Visibility.Collapsed;
}
}
}
else if ((this.chartView.Axes.Count > 0) && ((!ItemsSource.IsNull()) && ((IList)ItemsSource).Count > 0))
{
foreach (var actualAxis in this.chartView.ActualAxes)
{
if (actualAxis.Orientation.Equals(AxisOrientation.Y))
{
(actualAxis as LinearAxis).Maximum = null;
(actualAxis as LinearAxis).Minimum = null;
(actualAxis as LinearAxis).Maximum = MaximumAxisY;
(actualAxis as LinearAxis).Minimum = MinimumAxisY;
(actualAxis as LinearAxis).Visibility = Visibility.Visible;
(actualAxis as LinearAxis).ShowGridLines = ShowGridLinesY;
}
else if (actualAxis.Orientation.Equals(AxisOrientation.X))
{
if (actualAxis is DateTimeAxis)
{
if (!FieldForIndependentValue.IsNullOrEmpty() && FieldForIndependentValue.Contains("DateTime"))
{
(actualAxis as DateTimeAxis).Maximum = null;
(actualAxis as DateTimeAxis).Minimum = null;
(actualAxis as DateTimeAxis).Maximum = ((IList<ChartItems>)ItemsSource).Select(s => s.ValueXDateTime).LastOrDefault();
(actualAxis as DateTimeAxis).Minimum = ((IList<ChartItems>)ItemsSource).Select(s => s.ValueXDateTime).FirstOrDefault();
(actualAxis as DateTimeAxis).ShowGridLines = ShowGridLinesX;
(actualAxis as DateTimeAxis).Visibility = Visibility.Visible;
}
else
(actualAxis as DateTimeAxis).Visibility = Visibility.Collapsed;
}
else
{
if (!FieldForIndependentValue.IsNullOrEmpty() && FieldForIndependentValue.Contains("Double"))
{
(actualAxis as LinearAxis).Maximum = null;
(actualAxis as LinearAxis).Minimum = null;
if (IntervalAxisX > 0)
(actualAxis as LinearAxis).Interval = IntervalAxisX;
(actualAxis as LinearAxis).Maximum = ((IList<ChartItems>)ItemsSource).Select(s => s.ValueXDouble).LastOrDefault() + 0.5;
(actualAxis as LinearAxis).Minimum = ((IList<ChartItems>)ItemsSource).Select(s => s.ValueXDouble).FirstOrDefault() - 0.5;
(actualAxis as LinearAxis).Visibility = Visibility.Visible;
(actualAxis as LinearAxis).ShowGridLines = ShowGridLinesX;
}
else
(actualAxis as LinearAxis).Visibility = Visibility.Collapsed;
}
}
}
}
}
}
任何帮助将不胜感激。
最诚挚的问候, 古斯塔沃。
答案 0 :(得分:1)
事实证明,将自定义元素添加到图表并不困难。您应该检索图表区域,计算元素的位置,并在添加到任何面板时添加它们。
以下是完整的示例:
private Canvas canvas;
public MainWindow()
{
InitializeComponent();
chart.Loaded += this.OnChartLoaded;
}
private void OnChartLoaded(object sender, RoutedEventArgs e)
{
var chartArea = (Panel)chart.GetType().GetProperty("ChartArea", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(chart, null);
// create a canvas to which all text blocks will be added
this.canvas = new Canvas();
chartArea.Children.Add(this.canvas);
}
public void AddAllLineLabels()
{
// add a red label
double value = 15;
var text = new TextBlock() { Text = value.ToString(), Foreground = Brushes.Red };
AddTextToCanvas(canvas, text, value);
// add a green label
value = 19;
text = new TextBlock() { Text = value.ToString(), Foreground = Brushes.Green };
AddTextToCanvas(canvas, text, value);
}
private void AddTextToCanvas(Canvas canvas, TextBlock text, double value)
{
var valuesAxis = chart.ActualAxes.OfType<LinearAxis>().FirstOrDefault(ax => ax.Orientation == AxisOrientation.Y);
var min = valuesAxis.ActualMinimum.Value;
var max = valuesAxis.ActualMaximum.Value;
var maxPixels = valuesAxis.ActualHeight;
var valuePixels = (value - min) / (max - min) * maxPixels; // from the bottom edge to the value in pixels
Canvas.SetRight(text, 5); // 5 is a padding from the right edge, you can use any number
Canvas.SetBottom(text, valuePixels);
canvas.Children.Add(text);
}
如果您拨打AddAllLineLabels
方法,则会显示红色数字15和绿色数字19.