private static void OnCoordinateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { UIElement reference = d as UIElement; if (reference != null) { StackCanvas parent = VisualTreeHelper.GetParent(reference) as StackCanvas; if (parent != null) { parent.InvalidateArrange(); } } }
private void DoDrawMajorLabels() { ITicksProvider <T> majorTicksProvider = ticksProvider.MajorProvider; additionalLabelsCanvas.Children.Clear(); if (majorTicksProvider != null && majorLabelProvider != null) { additionalLabelsCanvas.Visibility = Visibility.Visible; Size renderSize = RenderSize; var majorTicks = majorTicksProvider.GetTicks(range, DefaultTicksProvider.DefaultTicksCount); double[] screenCoords = majorTicks.Ticks.Select(tick => createDataPoint(convertToDouble(tick))). Select(p => p.DataToScreen(transform)).Select(p => getCoordinate(p)).ToArray(); // todo this is not the best decision - when displaying, for example, // milliseconds, it causes to create hundreds and thousands of textBlocks. double rangesRatio = GetRangesRatio(majorTicks.Ticks.GetPairs().ToArray()[0], range); object info = majorTicks.Info; MajorLabelsInfo newInfo = new MajorLabelsInfo { Info = info, MajorLabelsCount = (int)Math.Ceiling(rangesRatio) }; var newMajorTicks = new TicksInfo <T> { Info = newInfo, Ticks = majorTicks.Ticks, TickSizes = majorTicks.TickSizes }; UIElement[] additionalLabels = MajorLabelProvider.CreateLabels(newMajorTicks); for (int i = 0; i < additionalLabels.Length; i++) { if (screenCoords[i].IsNaN()) { continue; } UIElement tickLabel = additionalLabels[i]; tickLabel.Measure(renderSize); StackCanvas.SetCoordinate(tickLabel, screenCoords[i]); StackCanvas.SetEndCoordinate(tickLabel, screenCoords[i + 1]); if (tickLabel is FrameworkElement) { ((FrameworkElement)tickLabel).LayoutTransform = additionalLabelTransform; } additionalLabelsCanvas.Children.Add(tickLabel); } } else { additionalLabelsCanvas.Visibility = Visibility.Collapsed; } }
private double staticAxisMargin = 1; // px private void DoDrawCommonLabels(MajorTickInfo <double>[] screenTicksX) { Size renderSize = RenderSize; commonLabelsCanvas.Children.Clear(); #if DEBUG if (labels != null) { foreach (FrameworkElement item in labels) { if (item != null) { Debug.Assert(item.Parent == null); } } } #endif double minCoordUnsorted = ToScreen(range.Min); double maxCoordUnsorted = ToScreen(range.Max); double minCoord = Math.Min(minCoordUnsorted, maxCoordUnsorted) - 1.5; double maxCoord = Math.Max(minCoordUnsorted, maxCoordUnsorted) + 1.5; double maxCoordDiff = (maxCoord - minCoord) / labels.Length / 2.0; double minCoordToAdd = minCoord - maxCoordDiff; double maxCoordToAdd = maxCoord + maxCoordDiff; for (int i = 0; i < ticks.Length; i++) { FrameworkElement tickLabel = (FrameworkElement)labels[i]; if (tickLabel == null) { continue; } Debug.Assert(((FrameworkElement)tickLabel).Parent == null); tickLabel.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity)); double screenX = screenTicksX[i].Value; double coord = screenX; tickLabel.HorizontalAlignment = HorizontalAlignment.Center; tickLabel.VerticalAlignment = VerticalAlignment.Center; if (isStaticAxis) { // getting real size of label tickLabel.Measure(renderSize); Size tickLabelSize = tickLabel.DesiredSize; if (Math.Abs(screenX - minCoord) < maxCoordDiff) { coord = minCoord + staticAxisMargin; if (placement.IsBottomOrTop()) { tickLabel.HorizontalAlignment = HorizontalAlignment.Left; } else { tickLabel.VerticalAlignment = VerticalAlignment.Top; } } else if (Math.Abs(screenX - maxCoord) < maxCoordDiff) { coord = maxCoord - getSize(tickLabelSize) / 2 - staticAxisMargin; if (!placement.IsBottomOrTop()) { tickLabel.VerticalAlignment = VerticalAlignment.Bottom; coord = maxCoord - staticAxisMargin; } } } // label is out of visible area if (coord < minCoord || coord > maxCoord) { continue; } if (coord.IsNaN()) { continue; } StackCanvas.SetCoordinate(tickLabel, coord); commonLabelsCanvas.Children.Add(tickLabel); } }