protected override void OnRender(DrawingContext drawingContext) { _segments.Children.Clear(); var angle = FilteredData.Map(0, 100, 0, 360); var radius = (_segments.RenderSize.Smallest() * CircleScale) / 2; var segmentWidth = radius * SegmentWidthPercentage; var inactivePath = new ArcPath(359.999, 0, segmentWidth, CircleScale, radius, _segments.RenderSize, null) { DataContext = this }; var activePath = new ArcPath(angle, AngleOffset, segmentWidth, CircleScale, radius, _segments.RenderSize, FilteredData) { DataContext = this }; inactivePath.Fill = SegmentSpaceBackground.GetMaterial(FallbackMaterialSet); activePath.Fill = RingForeground.GetMaterial(FallbackMaterialSet); //inactivePath.SetBinding(Shape.FillProperty, new Binding("SegmentSpaceBackground")); //activePath.SetBinding(Shape.FillProperty, new Binding("RingForeground")); _segments.Children.Add(inactivePath); _segments.Children.Add(activePath); base.OnRender(drawingContext); }
protected override void OnRender(DrawingContext drawingContext) { //TODO potential rendering loop. if (FilteredData.Count < 1) { FilteredData = DataFilter.Filter(DataSorter.Sort(Data)); base.OnRender(drawingContext); return; } visualContext = new NestedArcChartVisualContext(); PART_segments.Children.Clear(); PART_inactivesegments.Children.Clear(); PART_categorylabels.Children.Clear(); var context = new ProviderContext(FilteredData.Count); MaterialProvider.Reset(context); var fullArcDiameter = PART_main.RenderSize.Height - TopRingPadding; var fullArcWidth = fullArcDiameter - BottomRingPadding; var subArcAvailableWidth = fullArcWidth / FilteredData.Count; var subArcActualWidth = subArcAvailableWidth * SegmentWidthPercentage; var subRingOffset = (subArcAvailableWidth - subArcActualWidth) / 2; var fullRadius = PART_main.RenderSize.Width / 2; var centerPoint = new Point(0, fullRadius); if (FilteredData.Count < 1) { base.OnRender(drawingContext); return; } var max = FilteredData.MaxValue(); var trace = 0; foreach (var d in FilteredData) { var categoryVisualContext = new NestedArcCategoryVisualContext(); var materialSet = MaterialProvider.ProvideNext(context); categoryVisualContext.CategoryDataPoint = d; var arcDiameter = BottomRingPadding + (subArcAvailableWidth * trace) + subRingOffset; var inactiveArcPath = CalculatePath(centerPoint, arcDiameter, subArcActualWidth); inactiveArcPath.Fill = SegmentSpaceBackground.GetMaterial(materialSet); //BindingOperations.SetBinding(inactiveArcPath, Shape.FillProperty, new Binding("SegmentSpaceBackground") { Source = this }); categoryVisualContext.InactiveArcVisual = inactiveArcPath; PART_inactivesegments.Children.Add(inactiveArcPath); var activeArcAngle = d.Value.Map(0, max, 0, MaxArcAngle); var activeArcPath = CalculateActiveArcPath(centerPoint, arcDiameter, subArcActualWidth, activeArcAngle); categoryVisualContext.CategoryMaterialSet = materialSet; activeArcPath.Fill = SegmentForeground.GetMaterial(materialSet); activeArcPath.MouseOverFill = materialSet.GetMaterial(Luminosity.P700); activeArcPath.RenderTransformOrigin = new Point(.5, 1); activeArcPath.RenderTransform = new RotateTransform((IsLoaded ? 0 : 180), .5, .5); d.RenderedVisual = activeArcPath; categoryVisualContext.ActiveArcVisual = activeArcPath; PART_segments.Children.Add(activeArcPath); visualContext.CategoryVisuals.Add(categoryVisualContext); trace++; } var ltrace = 0; for (var x = FilteredData.Count - 1; x >= 0; x--) { var d = FilteredData[x]; var currentCategoryVisualContext = visualContext.CategoryVisuals[x]; var shape = (Shape)d.RenderedVisual; //.ShouldBeCastable<Shape>(); var renderedFill = (SolidColorBrush)shape.Fill; //.ShouldBeType<SolidColorBrush>(); var arcLabelMarginLeft = fullRadius + LeftArcLabelSpacing; var categoryLabel = new Label { Width = ValueLabelHorizontalSpacing, VerticalAlignment = VerticalAlignment.Top, HorizontalAlignment = HorizontalAlignment.Left, VerticalContentAlignment = VerticalAlignment.Center, HorizontalContentAlignment = HorizontalAlignment.Left, Margin = new Thickness(arcLabelMarginLeft, (ltrace * subArcAvailableWidth) + subRingOffset + 6, 0, 0), //Foreground = renderedFill.Lighten(.2), Foreground = ValueForeground.GetMaterial(currentCategoryVisualContext.CategoryMaterialSet), Content = d.CategoryName.ToUpper(), Height = subArcAvailableWidth, Padding = new Thickness(0), Opacity = IsLoaded ? 1 : 0, // TODO isloaded DataContext = this }; currentCategoryVisualContext.CategoryLabel = categoryLabel; //BindingOperations.SetBinding(categoryLabel, FontFamilyProperty, new Binding("ValueFontFamily") { Source = this }); //BindingOperations.SetBinding(categoryLabel, FontStyleProperty, new Binding("ValueFontStyle") { Source = this }); //BindingOperations.SetBinding(categoryLabel, FontWeightProperty, new Binding("ValueFontWeight") { Source = this }); //BindingOperations.SetBinding(categoryLabel, FontSizeProperty, new Binding("ValueFontSize") { Source = this }); categoryLabel.BindTextualPrimitive <ValuePrimitive>(this); var valuePercentLabel = new Label { Width = ValueLabelHorizontalSpacing, VerticalAlignment = VerticalAlignment.Top, HorizontalAlignment = HorizontalAlignment.Left, VerticalContentAlignment = VerticalAlignment.Center, HorizontalContentAlignment = HorizontalAlignment.Right, Margin = new Thickness(arcLabelMarginLeft, (ltrace * subArcAvailableWidth) + subRingOffset + 6, 0, 0), //Foreground = renderedFill.Lighten(.2), Foreground = ValueForeground.GetMaterial(currentCategoryVisualContext.CategoryMaterialSet), Content = d.Value + " Minutes", Height = subArcAvailableWidth, Padding = new Thickness(0), Opacity = IsLoaded ? 1 : 0, DataContext = this }; currentCategoryVisualContext.ValuePercentLabel = valuePercentLabel; valuePercentLabel.BindTextualPrimitive <ValuePrimitive>(this); var valueLabelLeftSpace = arcLabelMarginLeft + ValueLabelHorizontalSpacing; var valueLabelWidth = PART_main.RenderSize.Width - valueLabelLeftSpace; if (valueLabelWidth < 0) { valueLabelWidth = 0; } var valueLabel = new Label() { Width = valueLabelWidth, VerticalAlignment = VerticalAlignment.Top, HorizontalAlignment = HorizontalAlignment.Left, VerticalContentAlignment = VerticalAlignment.Center, HorizontalContentAlignment = HorizontalAlignment.Left, Foreground = SecondaryValueForeground.GetMaterial(currentCategoryVisualContext.CategoryMaterialSet), Margin = new Thickness(arcLabelMarginLeft + ValueLabelHorizontalSpacing, (ltrace * subArcAvailableWidth) + subRingOffset + 6, 0, 0), Content = $" = {Math.Round(d.Value / 60, 2)} Hours", //{Math.Round(d.Value * 48):n0} Height = subArcAvailableWidth, Opacity = IsLoaded ? 1 : 0, // TODO isloaded Padding = new Thickness(0), }; currentCategoryVisualContext.ValueLabel = valueLabel; valueLabel.BindTextualPrimitive <SecondaryValuePrimitive>(this); PART_categorylabels.Children.Add(categoryLabel); PART_categorylabels.Children.Add(valuePercentLabel); PART_categorylabels.Children.Add(valueLabel); ltrace++; } base.OnRender(drawingContext); }
protected override void OnRender(DrawingContext drawingContext) { PART_bars.Children.Clear(); PART_xAxis.Children.Clear(); PART_highlight.Children.Clear(); if (FilteredData.Count < 1) { base.OnRender(drawingContext); return; } var total = FilteredData.MaxValue(); var context = new ProviderContext(FilteredData.Count); var barAvailableWidth = PART_bars.RenderSize.Width / FilteredData.Count; var barActiveWidth = barAvailableWidth * SegmentWidthPercentage; var barLeftSpacing = (barAvailableWidth - barActiveWidth) / 2; var barLabelSize = RenderingExtensions.EstimateLabelRenderSize(BarTotalFontFamily, BarTotalFontSize); MaterialProvider.Reset(context); var xtrace = 0; foreach (var d in FilteredData) { var materialSet = MaterialProvider.ProvideNext(context); var axisLabel = new Label { Content = d.CategoryName, IsHitTestVisible = false, HorizontalContentAlignment = HorizontalAlignment.Center, VerticalContentAlignment = VerticalAlignment.Center, HorizontalAlignment = HorizontalAlignment.Left, VerticalAlignment = VerticalAlignment.Bottom, Width = barAvailableWidth, Margin = new Thickness(barAvailableWidth * xtrace, 0, 0, 0), Foreground = BarTotalForeground.GetMaterial(materialSet), DataContext = this }; axisLabel.BindTextualPrimitive <XAxisPrimitive>(this); PART_xAxis.Children.Add(axisLabel); xtrace++; } var horizontalTrace = 0d; var xAxisHeight = PART_xAxis.ActualHeight; var backHeight = PART_bars.RenderSize.Height - xAxisHeight; MaterialProvider.Reset(context); foreach (var d in FilteredData) { var materialSet = MaterialProvider.ProvideNext(context); var backRectangle = new Rectangle { Width = barActiveWidth, Height = backHeight, VerticalAlignment = VerticalAlignment.Bottom, HorizontalAlignment = HorizontalAlignment.Left, Margin = new Thickness(horizontalTrace + barLeftSpacing, 0, 0, xAxisHeight), Fill = SegmentSpaceBackground.GetMaterial(materialSet) }; //backRectangle.MouseEnter += (s, e) => barMouseEnter(d); //BindingOperations.SetBinding(backRectangle, Shape.FillProperty, new Binding("SegmentSpaceBackground") { Source = this }); PART_bars.Children.Add(backRectangle); var verticalTrace = 0d; var pathBuffer = new List <Shape>(); var height = d.Value.Map(0, total, 0, PART_bars.RenderSize.Height - xAxisHeight - barLabelSize.Height); var rectangle = new Rectangle { Width = barActiveWidth, Height = height + verticalTrace, Fill = SegmentForeground.GetMaterial(materialSet), VerticalAlignment = VerticalAlignment.Bottom, HorizontalAlignment = HorizontalAlignment.Left, Margin = new Thickness(horizontalTrace + barLeftSpacing, 0, 0, xAxisHeight) }; //rectangle.MouseEnter += (s, e) => barMouseEnter(d); //rectangle.MouseLeave += (s, e) => barMouseLeave(s, e, d, sd); rectangle.RenderTransform = new ScaleTransform(1, (IsLoaded ? 1 : 0), .5, 1); //TODO get rid of all isloaded conditional sets rectangle.RenderTransformOrigin = new Point(.5, 1); d.RenderedVisual = rectangle; pathBuffer.Add(rectangle); verticalTrace += height; for (var x = pathBuffer.Count - 1; x >= 0; x--) { var path = pathBuffer[x]; PART_bars.Children.Add(path); } var barLabel = new Label { Content = d.Value, IsHitTestVisible = false, HorizontalContentAlignment = HorizontalAlignment.Center, VerticalContentAlignment = VerticalAlignment.Center, HorizontalAlignment = HorizontalAlignment.Left, VerticalAlignment = VerticalAlignment.Bottom, Width = barAvailableWidth, Foreground = BarTotalForeground.GetMaterial(materialSet), Margin = new Thickness(horizontalTrace, 0, 0, xAxisHeight + verticalTrace), }; barLabel.BindTextualPrimitive <BarTotalPrimitive>(this); d.RenderedVisual = pathBuffer; PART_bars.Children.Add(barLabel); horizontalTrace += barAvailableWidth; } base.OnRender(drawingContext); }
protected override void OnRender(DrawingContext drawingContext) { //TODO potential rendering loop. if (FilteredData.Count < 1) { FilteredData = DataFilter.Filter(DataSorter.Sort(Data)); base.OnRender(drawingContext); return; } visualContext = new ParetoChartVisualContext(); PART_bars.Children.Clear(); PART_barlabels.Children.Clear(); PART_line.Children.Clear(); PART_xaxis.Children.Clear(); //_highlightGrid.Children.Clear(); var max = FilteredData.MaxValue(); var context = new ProviderContext(FilteredData.Count); var barAvailableWidth = (PART_bars.RenderSize.Width) / FilteredData.Count; var barActiveWidth = barAvailableWidth * SegmentWidthPercentage; var barLeftSpacing = (barAvailableWidth - barActiveWidth) / 2; var barLabelSize = RenderingExtensions.EstimateLabelRenderSize(BarTotalFontFamily, BarTotalFontSize); MaterialProvider.Reset(context); #region X-Axis Label Generation var xtrace = 0; foreach (var d in FilteredData) { var material = MaterialProvider.ProvideNext(context); var categoryVisualContext = new ParetoChartCategoryVisualContext(); var axisLabel = new Label { Content = d.CategoryName, IsHitTestVisible = false, HorizontalContentAlignment = HorizontalAlignment.Center, VerticalContentAlignment = VerticalAlignment.Center, HorizontalAlignment = HorizontalAlignment.Left, VerticalAlignment = VerticalAlignment.Bottom, Width = barAvailableWidth, Margin = new Thickness(barAvailableWidth * xtrace, 0, 0, 0), DataContext = this, Foreground = XAxisForeground.GetMaterial(material) }; axisLabel.BindTextualPrimitive <XAxisPrimitive>(this); categoryVisualContext.AxisLabel = axisLabel; PART_xaxis.Children.Add(axisLabel); visualContext.CategoryVisuals.Add(categoryVisualContext); xtrace++; } #endregion MaterialProvider.Reset(context); var horizontalTrace = 0d; var xAxisHeight = barLabelSize.Height; //_xAxisGrid.ActualHeight; var backHeight = PART_bars.RenderSize.Height - xAxisHeight; var trace = 0; foreach (var d in FilteredData) { var currentCategoryVisualContext = visualContext.CategoryVisuals[trace]; currentCategoryVisualContext.CategoryDataPoint = d; //if (barActiveWidth <= 0 || backHeight <= 0) return; //TODO fix var material = MaterialProvider.ProvideNext(context); currentCategoryVisualContext.CategoryMaterialSet = material; var backRectangle = new Rectangle { Width = barActiveWidth, Height = Math.Abs(backHeight), VerticalAlignment = VerticalAlignment.Bottom, HorizontalAlignment = HorizontalAlignment.Left, Fill = SegmentSpaceBackground.GetMaterial(material), Margin = new Thickness(horizontalTrace + barLeftSpacing, 0, 0, xAxisHeight) }; currentCategoryVisualContext.InactiveBarVisual = backRectangle; PART_bars.Children.Add(backRectangle); var height = d.Value.Map(0, max, 0, PART_bars.RenderSize.Height - xAxisHeight - barLabelSize.Height); var rectangle = new Rectangle { Width = barActiveWidth, Height = Math.Abs(height), Fill = SegmentForeground.GetMaterial(material), VerticalAlignment = VerticalAlignment.Bottom, HorizontalAlignment = HorizontalAlignment.Left, Margin = new Thickness(horizontalTrace + barLeftSpacing, 0, 0, xAxisHeight), RenderTransform = new ScaleTransform(1, 0, .5, 1), RenderTransformOrigin = new Point(.5, 1) }; currentCategoryVisualContext.ActiveBarRenderTransformScaleYAnimationAspect = new AnimationAspect <double, Transform, DoubleAnimation>(rectangle.RenderTransform, ScaleTransform.ScaleYProperty, 0, 1, animationState) { AccelerationRatio = AnimationParameters.AccelerationRatio, DecelerationRatio = AnimationParameters.DecelerationRatio, Duration = TimeSpan.FromMilliseconds(800) }; //TODO replace .RenderedVisual pairing method completely d.RenderedVisual = rectangle; PART_bars.Children.Add(rectangle); #region Bar Value Label Generation var beginBarLabelMargin = new Thickness(horizontalTrace, 0, 0, xAxisHeight); var actualBarLabelMargin = new Thickness(horizontalTrace, 0, 0, xAxisHeight + height); var barLabel = new Label { Content = d.Value, IsHitTestVisible = false, HorizontalContentAlignment = HorizontalAlignment.Center, VerticalContentAlignment = VerticalAlignment.Center, HorizontalAlignment = HorizontalAlignment.Left, VerticalAlignment = VerticalAlignment.Bottom, Width = barAvailableWidth, Foreground = BarTotalForeground.GetMaterial(material) }; barLabel.BindTextualPrimitive <BarTotalPrimitive>(this); currentCategoryVisualContext.BarLabelMarginAnimationAspect = new AnimationAspect <Thickness, Label, ThicknessAnimation>( barLabel, MarginProperty, beginBarLabelMargin, actualBarLabelMargin, animationState) { AccelerationRatio = AnimationParameters.AccelerationRatio, DecelerationRatio = AnimationParameters.DecelerationRatio, Duration = TimeSpan.FromMilliseconds(800) }; #endregion PART_barlabels.Children.Add(barLabel); horizontalTrace += barAvailableWidth; trace++; } var total = FilteredData.SumValue(); var availableLineGraphSize = new Size(PART_bars.ActualWidth - (DotRadius * 2), PART_bars.ActualHeight - (DotRadius * 2) - xAxisHeight); var startX = (barAvailableWidth / 2) - DotRadius; var verticalpttrace = 0d; var pttrace = 0; var pathSegments = new PathSegmentCollection(); var pathFigure = new PathFigure { Segments = pathSegments }; MaterialProvider.Reset(context); var isFirstPoint = true; foreach (var d in FilteredData) { var material = MaterialProvider.ProvideNext(context); var currentCategoryVisualContext = visualContext.CategoryVisuals[pttrace]; var nextPoint = new Point(startX + (barAvailableWidth * pttrace), verticalpttrace + xAxisHeight); var baseAnimationPoint = new Point(nextPoint.X, 0).LocalizeInCartesianSpace(PART_line); var actualNextPoint = nextPoint.LocalizeInCartesianSpace(PART_line); // TODO get rid of this var plottedPoint = IsLoaded ? actualNextPoint : baseAnimationPoint; if (isFirstPoint) { visualContext.PolyLineStartPointAnimationAspect = new AnimationAspect <Point, PathFigure, PointAnimation>( pathFigure, PathFigure.StartPointProperty, baseAnimationPoint, actualNextPoint, animationState) { AccelerationRatio = AnimationParameters.AccelerationRatio, DecelerationRatio = AnimationParameters.DecelerationRatio, Duration = TimeSpan.FromMilliseconds(800), }; isFirstPoint = false; } else { var lineSegment = new LineSegment(plottedPoint, true) { IsSmoothJoin = true }; pathSegments.Add(lineSegment); visualContext.LineSegmentVisuals.Add(new ParetoChartLineSegmentVisualContext { PointAnimationAspect = new AnimationAspect <Point, LineSegment, PointAnimation>(lineSegment, LineSegment.PointProperty, baseAnimationPoint, actualNextPoint, animationState) { AccelerationRatio = AnimationParameters.AccelerationRatio, DecelerationRatio = AnimationParameters.DecelerationRatio, Duration = TimeSpan.FromMilliseconds(800) } }); } var beginDotMargin = new Thickness(nextPoint.X, 0, 0, xAxisHeight); var actualDotMargin = new Thickness(nextPoint.X, 0, 0, nextPoint.Y); var dot = new Ellipse { Width = (DotRadius * 2), Height = (DotRadius * 2), VerticalAlignment = VerticalAlignment.Bottom, HorizontalAlignment = HorizontalAlignment.Left, Fill = DotFill.GetMaterial(material), Stroke = DotStroke.GetMaterial(material), }; BindingOperations.SetBinding(dot, Shape.StrokeThicknessProperty, new Binding("DotStrokeThickness") { Source = this }); currentCategoryVisualContext.DotMarginAnimationAspect = new AnimationAspect <Thickness, Ellipse, ThicknessAnimation>(dot, MarginProperty, beginDotMargin, actualDotMargin, animationState) { AccelerationRatio = AnimationParameters.AccelerationRatio, DecelerationRatio = AnimationParameters.DecelerationRatio, Duration = TimeSpan.FromMilliseconds(800) }; PART_line.Children.Add(dot); Panel.SetZIndex(dot, 50); verticalpttrace += d.Value.Map(0, total, 0, availableLineGraphSize.Height); pttrace++; } var path = new Path { VerticalAlignment = VerticalAlignment.Bottom, HorizontalAlignment = HorizontalAlignment.Left, Data = new PathGeometry { Figures = new PathFigureCollection { pathFigure } }, Margin = new Thickness(DotRadius, 0, 0, xAxisHeight + DotRadius), Stroke = LineStroke.GetMaterial(FallbackMaterialSet), }; BindingOperations.SetBinding(path, Shape.StrokeThicknessProperty, new Binding("LineStrokeThickness") { Source = this }); PART_line.Children.Add(path); base.OnRender(drawingContext); }
protected override void OnRender(DrawingContext drawingContext) { visualContext = new HorizontalBarChartVisualContext(); PART_bars.Rows = FilteredData.Count; PART_yaxis.Rows = FilteredData.Count; PART_bars.Children.Clear(); PART_yaxis.Children.Clear(); if (FilteredData.Count < 1) { base.OnRender(drawingContext); return; } var effeectiveTargetRenderingMax = CommonFixedRangeMax > 0 ? CommonFixedRangeMax : FilteredData.MaxValue(); var context = new ProviderContext(FilteredData.Count); MaterialProvider.Reset(context); double YAxisRenderingWidth; if (CommonYAxisWidth <= 0) { var maxYAxisTextLength = FilteredData.Select(d => RenderingExtensions.EstimateLabelRenderSize( YAxisFontFamily, YAxisFontSize, d.CategoryName)) .Select(renderSize => renderSize.Width).Concat(new[] { 0.0 }).Max(); YAxisRenderingWidth = maxYAxisTextLength; } else { YAxisRenderingWidth = CommonYAxisWidth; } PART_yaxis.Width = YAxisRenderingWidth; var maxValueTextLength = FilteredData.Select(d => RenderingExtensions.EstimateLabelRenderSize( BarTotalFontFamily, BarTotalFontSize, new Thickness(10, 5, 10, 5), d.Value.ToString(CultureInfo.InvariantCulture))) .Select(renderSize => renderSize.Width).Concat(new[] { 0.0 }).Max(); var totalAvailableVerticalSpace = 0.0; if (CommonFixedRowHeight > 0) { totalAvailableVerticalSpace = CommonFixedRowHeight; } else { totalAvailableVerticalSpace = PART_bars.ActualHeight / FilteredData.Count; } var totalAvailableHorizontalExpanse = PART_bars.ActualWidth; var totalAvailableHorizontalSpace = totalAvailableHorizontalExpanse - maxValueTextLength; var actualBarHeight = totalAvailableVerticalSpace * SegmentWidthPercentage; foreach (var d in FilteredData) { var barContext = new HorizontalBarChartSegmentVisualContext(); var barWidth = d.Value.Map(0, effeectiveTargetRenderingMax, 0, totalAvailableHorizontalSpace); var materialSet = MaterialProvider.ProvideNext(context); var barGrid = new Grid(); var bar = new Rectangle { Fill = SegmentForeground.GetMaterial(materialSet), Height = actualBarHeight, Width = barWidth, HorizontalAlignment = HorizontalAlignment.Left }; barGrid.Children.Add(bar); barContext.ActiveBar = bar; var barSpaceBackground = new Rectangle { Fill = SegmentSpaceBackground.GetMaterial(materialSet), Height = actualBarHeight, Width = totalAvailableHorizontalExpanse, HorizontalAlignment = HorizontalAlignment.Left }; barGrid.Children.Add(barSpaceBackground); barContext.InactiveBar = barSpaceBackground; var barLabel = new Label { Content = d.Value, IsHitTestVisible = false, HorizontalContentAlignment = HorizontalAlignment.Center, VerticalContentAlignment = VerticalAlignment.Center, HorizontalAlignment = HorizontalAlignment.Left, //VerticalAlignment = VerticalAlignment.Center , Width = maxValueTextLength, Padding = new Thickness(10, 5, 10, 5), Foreground = BarTotalForeground.GetMaterial(materialSet), Margin = new Thickness(barWidth, 0, 0, 0), }; barLabel.BindTextualPrimitive <BarTotalPrimitive>(this); barGrid.Children.Add(barLabel); barContext.BarLabel = barLabel; PART_bars.Children.Add(barGrid); var yaxisLabel = new Label { Content = TextRenderingStrategy.ProvideText(d.CategoryName, YAxisRenderingWidth, YAxisFontFamily, YAxisFontSize, YAxisPadding), IsHitTestVisible = false, HorizontalContentAlignment = HorizontalAlignment.Left, VerticalContentAlignment = VerticalAlignment.Center, ToolTip = d.CategoryName, //HorizontalAlignment = HorizontalAlignment.Left, //VerticalAlignment = VerticalAlignment.Center, Width = YAxisRenderingWidth, Foreground = YAxisForeground.GetMaterial(materialSet), Margin = new Thickness(0, 0, 0, 0), Padding = YAxisPadding }; yaxisLabel.BindTextualPrimitive <YAxisPrimitive>(this); PART_yaxis.Children.Add(yaxisLabel); visualContext.BarVisuals.Add(barContext); } base.OnRender(drawingContext); }