I am using Telerik (RadPieChart) with WPF. What I want to do is add a small space between the bars. I am not asking about the space between the series, as that is already available, but about a smaller space between the bars just as shown in the image examples below.
Here is what I have now:
And this is how I would like my Bar Chart to look like with a small space between them:
This is my source code:
private BarSeries CreateBarSeries(KeyValuePair<ChartSerie, List<ChartDataPoint>> chartSeries, ChartLegendSettings legendSettings, int colorPaletteIndex)
{
var isStackMode = chartSeries.Key.CombineMode == SeriesCombineMode.Stack;
var barSerie = new BarSeries()
{
VerticalAxis = CreateMultipleVerticalAxis(chartSeries, colorPaletteIndex, out var multipleVerticalAxis) ? multipleVerticalAxis : null,
LegendSettings = legendSettings,
StackGroupKey = chartSeries.Key.Group,
Opacity = 0.8,
ZIndex = 120,
CombineMode = string.IsNullOrEmpty(chartSeries.Key.Group)
? ChartSeriesCombineMode.Cluster
: (isStackMode ? ChartSeriesCombineMode.Stack : ChartSeriesCombineMode.Stack100),
// start animations
//PointAnimation = new ChartMoveAnimation()
//{
// MoveAnimationType = MoveAnimationType.Bottom,
// Duration = new TimeSpan(0, 0, 0, 0, 600),
// Delay = new TimeSpan(0, 0, 0, 0, 155),
// //Easing = new ElasticEase()
// //{
// // EasingMode = EasingMode.EaseOut,
// //},
//},
LabelDefinitions =
{
// set the clarion format for the labels
new ChartSeriesLabelDefinition()
{
Template = new DataTemplate()
{
VisualTree = GetSeriesFormat(chartSeries),
}
}
}
};
// this is the color of bar series
if (chartSeries.Key.ColorHex != null)
{
Style style = new Style(typeof(Border));
style.Setters.Add(new Setter(Border.BackgroundProperty, (SolidColorBrush)(new BrushConverter().ConvertFrom(chartSeries.Key.ColorHex))));
barSerie.DefaultVisualStyle = style;
}
foreach (ChartDataPoint serie in chartSeries.Value)
{
barSerie.DataPoints.Add(new CategoricalDataPoint()
{
Category = serie.XPoint.Label,
Value = (double?)serie.Value,
});
}
return barSerie;
}
The answer:
For some reason adding the BorderThickness to the Style as suggested in one of the answers did not do the trick, although BorderThicknes should be the solution. So I added a PointTemplate with a VisualTree and there I defined the BorderThickness. Now it is working perfectly.
private BarSeries CreateBarSeries(KeyValuePair<ChartSerie, List<ChartDataPoint>> chartSeries, ChartLegendSettings legendSettings, int colorPaletteIndex)
{
var seriesPredefinedColor = this.ChartBase.Palette.GlobalEntries[colorPaletteIndex].Fill;
FrameworkElementFactory borderFramework = new FrameworkElementFactory(typeof(Border));
borderFramework.SetValue(Border.BackgroundProperty, ColorService.BrushFromHex(chartSeries.Key.ColorHex) ?? seriesPredefinedColor);
borderFramework.SetValue(Border.OpacityProperty, 0.8D);
borderFramework.SetValue(Border.BorderThicknessProperty, new Thickness(2));
borderFramework.AddHandler(Border.MouseEnterEvent, new MouseEventHandler((sender, args) =>
{
var seriesBorder = (Border)sender;
//seriesBorder.BorderBrush = new SolidColorBrush(Colors.Black);
//seriesBorder.BorderThickness = new Thickness(1);
seriesBorder.Opacity = 1;
}));
borderFramework.AddHandler(Border.MouseLeaveEvent, new MouseEventHandler((sender, args) =>
{
var seriesBorder = (Border)sender;
//seriesBorder.BorderBrush = new SolidColorBrush(Colors.Black);
//seriesBorder.BorderThickness= new Thickness(1);
seriesBorder.Opacity = 0.8;
}));
var isStackMode = chartSeries.Key.CombineMode == SeriesCombineMode.Stack;
var barSerie = new BarSeries()
{
VerticalAxis = CreateMultipleVerticalAxis(chartSeries, colorPaletteIndex, out var multipleVerticalAxis) ? multipleVerticalAxis : null,
LegendSettings = legendSettings,
StackGroupKey = chartSeries.Key.Group,
ZIndex = 120,
IsHitTestVisible = true,
CombineMode = string.IsNullOrEmpty(chartSeries.Key.Group)
? ChartSeriesCombineMode.Cluster
: (isStackMode ? ChartSeriesCombineMode.Stack : ChartSeriesCombineMode.Stack100),
// start animations
//PointAnimation = new ChartMoveAnimation()
//{
// MoveAnimationType = MoveAnimationType.Bottom,
// Duration = new TimeSpan(0, 0, 0, 0, 600),
// Delay = new TimeSpan(0, 0, 0, 0, 155),
// //Easing = new ElasticEase()
// //{
// // EasingMode = EasingMode.EaseOut,
// //},
//},
LabelDefinitions =
{
// set the clarion format for the labels
new ChartSeriesLabelDefinition()
{
Template = new DataTemplate()
{
VisualTree = GetSeriesFormat(chartSeries),
}
}
},
PointTemplate = new DataTemplate()
{
VisualTree = borderFramework,
}
};
// this is the color of bar series
//if (chartSeries.Key.ColorHex != null)
//{
// Style style = new Style(typeof(Border));
// style.Setters.Add(new Setter(Border.BackgroundProperty, (SolidColorBrush)(new BrushConverter().ConvertFrom(chartSeries.Key.ColorHex))));
// barSerie.DefaultVisualStyle = style;
//}
foreach (ChartDataPoint serie in chartSeries.Value)
{
barSerie.DataPoints.Add(new CategoricalDataPoint()
{
Category = serie.XPoint.Label,
Value = (double?)serie.Value,
});
}
return barSerie;
}
Set the BorderThickness property of the DefaultVisualStyle of the BarSeries:
// this is the color of bar series
if (chartSeries.Key.ColorHex != null)
{
Style style = new Style(typeof(Border));
style.Setters.Add(new Setter(Border.BackgroundProperty, (SolidColorBrush)(new BrushConverter().ConvertFrom(chartSeries.Key.ColorHex))));
style.Setters.Add(new Setter(Border.BorderThicknessProperty, new Thickness(2.0)));
barSerie.DefaultVisualStyle = style;
}
have you look into this ? seem default is 0 mean bar take all the space
Scale.SpacingSlotCount Property
Determines the number of space slots that will be left around the DataPoints per category slot, measured relatively to the DataPoint
slot's width: Empty Space = SpacingSlotCount * DataPoint_SlotWidth
Namespace: Telerik.Reporting
Assembly: Telerik.Reporting (in Telerik.Reporting.dll) Version: 12.1.18.816 (12.1.18.816)
Related
I am using ChartView Telerik WPF Library. I want the points to get bigger when the user hovers over them. But for some reason it is not working as expected. The Ellipse gets bigger but it does not resize correctly. But I don't understand why. The other properties as border color and thickness are working correctly.
Can someone tell me what am I missing here ?
This is how it looks currently when I try to resize the point :
Here is the Source Code:
private FrameworkElementFactory AddPointsToSeries(KeyValuePair<ChartSerie, List<ChartDataPoint>> chartSeries, int colorPaletteIndex)
{
var seriesPredefinedColor = this.ChartBase.Palette.GlobalEntries[colorPaletteIndex].Fill;
FrameworkElementFactory frameworkElement = new FrameworkElementFactory(typeof(Ellipse));
frameworkElement.SetValue(Ellipse.FillProperty, ColorService.BrushFromHex(chartSeries.Key.ColorHex) ?? seriesPredefinedColor);
frameworkElement.SetValue(Ellipse.HeightProperty, 9.0D);
frameworkElement.SetValue(Ellipse.WidthProperty, 9.0D);
frameworkElement.AddHandler(Ellipse.MouseEnterEvent, new MouseEventHandler((sender, args) =>
{
Ellipse ellipse = (Ellipse)sender;
ellipse.Stroke = ColorService.BrushFromHex(ColorService.BlendHex((chartSeries.Key.ColorHex ?? ColorService.BrushToHex(seriesPredefinedColor)), "#000000", 0.4));
// this is not correctly applied!
ellipse.Width = 15;
ellipse.Height = 15;
ellipse.StrokeThickness = 2;
}));
frameworkElement.AddHandler(Ellipse.MouseLeaveEvent, new MouseEventHandler((sender, args) =>
{
Ellipse ellipse = (Ellipse)sender;
ellipse.Height = 8;
ellipse.Width = 8;
ellipse.Stroke = null;
}));
return frameworkElement;
}
// Here I create the Line Series and here I use the AddPointsToSeries Method
private LineSeries CreateLineSeries(KeyValuePair<ChartSerie, List<ChartDataPoint>> chartSeries, ChartLegendSettings legendSettings,
int colorPaletteIndex)
{
FrameworkElementFactory addPoints = AddPointsToSeries(chartSeries, colorPaletteIndex);
var lineSerie = new LineSeries()
{
VerticalAxis = CreateMultipleVerticalAxis(chartSeries, colorPaletteIndex, out var multipleVerticalAxis) ? multipleVerticalAxis : null,
ZIndex = 150, // the line series should always be displayed on top of other series.
StrokeThickness = 3.5,
LegendSettings = (SeriesLegendSettings)legendSettings,
Opacity = 0.8,
StackGroupKey = chartSeries.Key.Group,
CombineMode = string.IsNullOrEmpty(chartSeries.Key.Group) ? ChartSeriesCombineMode.None : ChartSeriesCombineMode.Stack,
PointTemplate = new DataTemplate()
{
VisualTree = addPoints,
},
};
// this is the color of line series
if (chartSeries.Key.ColorHex != null)
{
lineSerie.Stroke = (SolidColorBrush)(new BrushConverter().ConvertFrom(chartSeries.Key.ColorHex));
}
foreach (ChartDataPoint serie in chartSeries.Value)
{
lineSerie.DataPoints.Add(new CategoricalDataPoint()
{
Category = serie.XPoint.Label,
Value = (double?)serie.Value,
});
}
return lineSerie;
}
My question was answered my Martin Ivanov:
This behavior comes from the size caching mechanism of the chart. Basically, the control is setting the size of the visual when initially loaded and then it doesn't change it unless something on the chart's API changes. In order to achieve your requirement you can wrap the ellipse in a Grid panel and its Width and Height properties to be the same (or little bigger) then the size of the bigger ellipse.
This is the solution:
private FrameworkElementFactory AddPointsToSeries(KeyValuePair<ChartSerie, List<ChartDataPoint>> chartSeries, int colorPaletteIndex)
{
var seriesPredefinedColor = this.ChartBase.Palette.GlobalEntries[colorPaletteIndex].Fill;
Brush brush = chartSeries.Key.ColorHex == null ? (seriesPredefinedColor) : ColorService.HexToBrush(chartSeries.Key.ColorHex);
Brush mouseOnEnterColor = new SolidColorBrush(ColorService.ChangeColorLightness(ColorService.BrushToColor(brush), 0.8));
double ellipseMouseOverStrokeThickness = 2;
double ellipseMouseOverHeightWidth = 13;
double ellipseStrokeThickness = 1;
double ellipseHeightWidth = 9;
FrameworkElementFactory frameworkElement = new FrameworkElementFactory(typeof(Ellipse));
frameworkElement.SetValue(Ellipse.FillProperty, brush);
frameworkElement.SetValue(Ellipse.MarginProperty, new Thickness(-4.5));
frameworkElement.SetValue(Ellipse.HeightProperty, ellipseHeightWidth);
frameworkElement.SetValue(Ellipse.WidthProperty, ellipseHeightWidth);
frameworkElement.SetValue(Ellipse.StrokeProperty, new SolidColorBrush(Colors.White));
frameworkElement.SetValue(Ellipse.StrokeThicknessProperty, ellipseStrokeThickness);
frameworkElement.AddHandler(Ellipse.MouseEnterEvent, new MouseEventHandler((sender, args) =>
{
Ellipse ellipse = (Ellipse)sender;
ellipse.Fill = new SolidColorBrush(Colors.White);
ellipse.Stroke = mouseOnEnterColor;
ellipse.StrokeThickness = ellipseMouseOverStrokeThickness;
ellipse.Width = ellipseMouseOverHeightWidth;
ellipse.Height = ellipseMouseOverHeightWidth;
}));
frameworkElement.AddHandler(Ellipse.MouseLeaveEvent, new MouseEventHandler((sender, args) =>
{
Ellipse ellipse = (Ellipse)sender;
ellipse.Stroke = new SolidColorBrush(Colors.White);
ellipse.Fill = brush;
ellipse.StrokeThickness = ellipseStrokeThickness;
ellipse.Height = ellipseHeightWidth;
ellipse.Width = ellipseHeightWidth;
}));
FrameworkElementFactory stackPanelFactory = new FrameworkElementFactory(typeof(Grid));
stackPanelFactory.SetValue(Grid.HeightProperty, ellipseMouseOverHeightWidth + ellipseMouseOverStrokeThickness);
stackPanelFactory.SetValue(Grid.WidthProperty, ellipseMouseOverHeightWidth + ellipseMouseOverStrokeThickness);
stackPanelFactory.AppendChild(frameworkElement);
return stackPanelFactory;
}
Now it looks like this:
I'm trying to recreate the slide-up part animation of the notification-queue on Windows 10 live tiles with an image I have ontop of another image. Below I have a "slide-up" storyboard working...but it's not the same.
Is the live tile ani actually growing in height as it slides up over the first?
I can't "see/figure" what it's doing.
public static async Task SlideUp(FrameworkElement element, double duration, int to = 0)
{
var tempTransform = new TranslateTransform();
element.RenderTransform = tempTransform;
var animation = new DoubleAnimation
{
From = element.ActualHeight * 2,
To = to,
Duration = TimeSpan.FromSeconds(duration),
EasingFunction = new CubicEase { EasingMode = EasingMode.EaseOut }
};
Storyboard.SetTargetProperty(animation, "Y");
Storyboard.SetTarget(animation, tempTransform);
var sb = new Storyboard();
sb.Duration = animation.Duration;
sb.Children.Add(animation);
await sb.BeginAsync();
}
The flip part of the animations would be nice too.
You could take a look at the DoubleAnimationUsingKeyFrames class:
https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.media.animation.doubleanimationusingkeyframes.aspx
Update: You can also animate the Height of the image
public static async Task SlideUp(FrameworkElement element, double duration, int to = 0)
{
var trTransform = new TranslateTransform();
element.RenderTransform = trTransform;
double from = element.ActualHeight;
duration *= 1.5;
var animation = new DoubleAnimationUsingKeyFrames();
animation.KeyFrames.Add(new DiscreteDoubleKeyFrame
{
KeyTime = KeyTime.FromTimeSpan(new TimeSpan(0,0,0,0)),
Value = from / 2
});
var ks = new KeySpline { ControlPoint1 = new Point(0.0, 0.0), ControlPoint2 = new Point(0.9, 0.1) };
animation.KeyFrames.Add(new SplineDoubleKeyFrame
{
KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(duration*1000/2)),
KeySpline = ks,
Value = (from - to) / 3 + to
});
var ks2 = new KeySpline { ControlPoint1 = new Point(0.1, 0.9), ControlPoint2 = new Point(0.2, 1.0) };
animation.KeyFrames.Add(new SplineDoubleKeyFrame
{
KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(duration)),
KeySpline = ks2,
Value = to
});
Storyboard.SetTargetProperty(animation, "Y");
Storyboard.SetTarget(animation, trTransform);
var sb = new Storyboard();
sb.Duration = animation.Duration;
sb.Children.Add(animation);
DoubleAnimationUsingKeyFrames resizeHeightAnimation = new DoubleAnimationUsingKeyFrames()
{
EnableDependentAnimation = true
};
resizeHeightAnimation.KeyFrames.Add(new DiscreteDoubleKeyFrame
{
KeyTime = KeyTime.FromTimeSpan(new TimeSpan(0, 0, 0, 0)),
Value = 0
});
var heightSpline1 = new KeySpline { ControlPoint1 = new Point(0.0, 0.0), ControlPoint2 = new Point(0.9, 0.1) };
resizeHeightAnimation.KeyFrames.Add(new SplineDoubleKeyFrame
{
KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(duration * 1000 / 2)),
KeySpline = heightSpline1,
Value = from / 3
});
var heightSpline2 = new KeySpline { ControlPoint1 = new Point(0.1, 0.9), ControlPoint2 = new Point(0.2, 1.0) };
resizeHeightAnimation.KeyFrames.Add(new SplineDoubleKeyFrame
{
KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(duration)),
KeySpline = heightSpline2,
Value = from
});
Storyboard.SetTarget(resizeHeightAnimation, element);
Storyboard.SetTargetProperty(resizeHeightAnimation, "RenderTransform.Height");
sb.Children.Add(resizeHeightAnimation);
sb.Begin();
}
If that looks to laggy for you, you can also try setting the VerticalAlignment of the element to Bottom and remove the position animation part of the method.
I am making a basic note taking app using C# in Xamarin Studio and have been following along with a course online.
Problem is that the code examples provided contain a lot of repetitive code which is making updating the app increasingly hard.
I labelled the relevant code below which is pertinent to two very similar classes, EditNoteViewController.cs and AddNoteViewController.cs, how can I extract the code out so that I can call it just once?
Alternatively I am looking at extracting it all into one class and having a conditional flow rendering different attributes based on whether the user is creating or updating a note.
EditNoteController.cs
using System;
using UIKit;
namespace NoteTaker.iOS
{
public class EditNoteViewController : UIViewController
{
Note note;
public EditNoteViewController (Note _note)
{
note = _note;
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
this.NavigationController.NavigationBar.BarTintColor = UIColor.FromRGB (255, 0, 255); // Repeated code. Also used in MainViewController.cs
this.Title = "Edit Note";
this.NavigationController.NavigationBar.TitleTextAttributes = new UIStringAttributes () { ForegroundColor = UIColor.White };
this.NavigationController.NavigationBar.TintColor = UIColor.White;
this.View.BackgroundColor = UIColor.White;
var titleEntryBox = new UITextField () {
Frame = new CoreGraphics.CGRect (0, 100, View.Bounds.Width, 45), // Repeated code
BackgroundColor = UIColor.LightGray,
TextColor = UIColor.Black,
Text = note.title
};
var descriptionLabel = new UILabel () {
Frame = new CoreGraphics.CGRect (10, 180, 250, 35),
Text = "Description",
};
var descriptionEntryBox = new UITextView () {
Frame = new CoreGraphics.CGRect (0, 220, View.Bounds.Width, 100), // Repeated code
BackgroundColor = UIColor.LightGray,
TextColor = UIColor.Black,
Text = note.description
};
var updateButton = new UIButton () {
Frame = new CoreGraphics.CGRect (10, 340, 120, 45)
}; // Repeated code
updateButton.SetTitle ("Update", UIControlState.Normal);
updateButton.BackgroundColor = UIColor.FromRGB (255, 0, 255);
updateButton.SetTitleColor (UIColor.White, UIControlState.Normal);
this.View.Add (titleEntryBox);
this.View.Add (descriptionLabel);
this.View.Add (descriptionEntryBox);
this.View.Add (updateButton);
updateButton.TouchUpInside += (sender, e) => {
if (titleEntryBox.Text.Length < 4)
return;
var noteToUpdate = new Note () {
ID = note.ID,
title = titleEntryBox.Text,
description = descriptionEntryBox.Text,
dateCreated = DateTime.Now
};
Database.updateNote (noteToUpdate);
this.NavigationController.PopViewController (true);
};
}
}
}
AddNoteViewController.cs
using System;
using UIKit;
namespace NoteTaker.iOS
{
public class AddNoteViewController : UIViewController
{
public AddNoteViewController ()
{
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
this.NavigationController.NavigationBar.BarTintColor = UIColor.FromRGB (255, 0, 255);
this.Title = "New Note";
this.NavigationController.NavigationBar.TitleTextAttributes = new UIStringAttributes () { ForegroundColor = UIColor.White };
this.NavigationController.NavigationBar.TintColor = UIColor.White;
this.View.BackgroundColor = UIColor.White;
var titleEntryBox = new UITextField () {
Frame = new CoreGraphics.CGRect (0, 100, View.Bounds.Width, 45),
BackgroundColor = UIColor.LightGray,
Placeholder = "Enter title...",
TextColor = UIColor.Black
};
var descriptionLabel = new UILabel () {
Frame = new CoreGraphics.CGRect (10, 180, 250, 35),
Text = "Enter description below"
};
var descriptionEntryBox = new UITextView () {
Frame = new CoreGraphics.CGRect (0, 220, View.Bounds.Width, 100),
BackgroundColor = UIColor.LightGray,
TextColor = UIColor.Black
};
var saveButton = new UIButton () {
Frame = new CoreGraphics.CGRect (10, 340, 120, 45)
};
saveButton.SetTitle ("Save Note", UIControlState.Normal);
saveButton.BackgroundColor = UIColor.FromRGB (255, 0, 255);
saveButton.SetTitleColor (UIColor.White, UIControlState.Normal);
this.View.Add (titleEntryBox);
this.View.Add (descriptionLabel);
this.View.Add (descriptionEntryBox);
this.View.Add (saveButton);
saveButton.TouchUpInside += (sender, e) => {
if (titleEntryBox.Text.Length < 4)
return;
var noteToSave = new Note () {
title = titleEntryBox.Text,
description = descriptionEntryBox.Text,
dateCreated = DateTime.Now
};
Database.InsertNote (noteToSave);
titleEntryBox.Text = "";
descriptionEntryBox.Text = "";
};
}
}
}
There are lots of different ways to approach a problem like this; this is just a simple example - passing a null into the controller will cause it to "Add", otherwise it will act as an "Edit" page
public class NoteViewController : UIViewController
{
Note note;
public NoteViewController (Note _note)
{
note = _note;
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
this.NavigationController.NavigationBar.BarTintColor = UIColor.FromRGB (255, 0, 255); // Repeated code. Also used in MainViewController.cs
this.Title = note == null ? "Add Note" : "Edit Note";
this.NavigationController.NavigationBar.TitleTextAttributes = new UIStringAttributes () { ForegroundColor = UIColor.White };
this.NavigationController.NavigationBar.TintColor = UIColor.White;
this.View.BackgroundColor = UIColor.White;
var titleEntryBox = new UITextField () {
Frame = new CoreGraphics.CGRect (0, 100, View.Bounds.Width, 45), // Repeated code
BackgroundColor = UIColor.LightGray,
TextColor = UIColor.Black,
Text = note == null ? string.Empty : note.title
};
var descriptionLabel = new UILabel () {
Frame = new CoreGraphics.CGRect (10, 180, 250, 35),
Text = "Description",
};
var descriptionEntryBox = new UITextView () {
Frame = new CoreGraphics.CGRect (0, 220, View.Bounds.Width, 100), // Repeated code
BackgroundColor = UIColor.LightGray,
TextColor = UIColor.Black,
Text = note == null ? string.Empty : note.description
};
var button = new UIButton () {
Frame = new CoreGraphics.CGRect (10, 340, 120, 45)
}; // Repeated code
if (note == null) {
button.SetTitle ("Add", UIControlState.Normal);
} else {
button.SetTitle ("Update", UIControlState.Normal);
}
button.BackgroundColor = UIColor.FromRGB (255, 0, 255);
button.SetTitleColor (UIColor.White, UIControlState.Normal);
this.View.Add (titleEntryBox);
this.View.Add (descriptionLabel);
this.View.Add (descriptionEntryBox);
this.View.Add (button);
button.TouchUpInside += (sender, e) => {
if (note == null) {
var noteToSave = new Note () {
title = titleEntryBox.Text,
description = descriptionEntryBox.Text,
dateCreated = DateTime.Now
};
Database.InsertNote (noteToSave);
titleEntryBox.Text = "";
descriptionEntryBox.Text = "";
} else {
if (titleEntryBox.Text.Length < 4)
return;
var noteToUpdate = new Note () {
ID = note.ID,
title = titleEntryBox.Text,
description = descriptionEntryBox.Text,
dateCreated = DateTime.Now
};
Database.updateNote (noteToUpdate);
this.NavigationController.PopViewController (true);
}
};
}
}
I have a basic asp.net chart writing into the response stream.
Changing BackColor to Color.Transparent and every text being bold automaticly. Searched many posts/forums about this issue but couldnt find any solution.
This my Chart builder Code.
public static void BuildChart(Chart chart, IEnumerable<MultiMeasureData> source, Measure[] measures,bool transparent)
{
var ca = chart.ChartAreas.FirstOrDefault();
if (ca == null)
chart.ChartAreas.Add(ca = new ChartArea());
//added for transparency support.
ca.BackImageTransparentColor = Color.White;
ca.BackColor = Color.Transparent;
Series s = new Series("Ölçümler");
s.Font = new Font(FontFamily.GenericSansSerif, 10, FontStyle.Regular);
chart.Series.Add(s);
var leg = new Legend("legend1");
leg.Docking = Docking.Top;
//added for transparenct support.
leg.BackColor = Color.Transparent;
leg.Font = new Font("Arial", 8, FontStyle.Regular);
chart.Legends.Add(leg);
chart.Palette = System.Windows.Forms.DataVisualization.Charting.ChartColorPalette.Berry;
//Transparency.
chart.BackColor = transparent ? Color.Transparent : Color.White;
//chart.BackSecondaryColor = Color.FromArgb(187, 205, 237);
//chart.BackGradientStyle = System.Windows.Forms.DataVisualization.Charting.GradientStyle.LeftRight;
if (source != null)
{
if (measures.Length > 0)
{
ca.AxisX.LabelStyle.Format = "dd.MM.yy";
ca.AxisX.MinorGrid.Enabled = true;
ca.AxisX.MinorGrid.Interval = 12;
ca.AxisX.MinorGrid.IntervalType = DateTimeIntervalType.Hours;
ca.AxisX.MinorGrid.LineColor = Color.LightGray;
ca.BackGradientStyle = System.Windows.Forms.DataVisualization.Charting.GradientStyle.HorizontalCenter;
// ca.BackColor = Color.FromArgb(134, 218, 239);
ca.AxisY.LabelStyle.Format = "{0}" + measures.First().Type.Unit;
ca.AxisY.LabelStyle.ForeColor = Color.Black;
ca.AxisY.LabelStyle.Font = new Font(FontFamily.GenericSansSerif, 10, FontStyle.Regular);
ca.AxisX.LabelStyle.ForeColor = Color.Black;
ca.AxisX.LabelStyle.Font = new Font(FontFamily.GenericSansSerif, 10, FontStyle.Regular);
ca.AxisX.MajorGrid.LineColor = Color.Silver;
ca.AxisY.MajorGrid.LineColor = Color.Silver;
// var tm = (e - s).TotalMinutes / 10;
var data = source
.Select(a =>
{
var ret = new { Time = a.Time, Values = new double?[measures.Length] };
for (int i = 0; i < measures.Length; i++)
ret.Values[i] = a.Values[i].HasValue ? a.Values[i] / measures[i].Type.ValueScale:null;
return ret;
}
).OrderBy(a => a.Time);
var times = data.Select(a => a.Time).ToArray();
for (int i = 0; i < measures.Length; i++)
{
var serie = new Series(measures[i].Type.Name) { ChartType = SeriesChartType.Spline };
serie.XValueType = ChartValueType.DateTime;
serie.ShadowColor = Color.Gray;
serie.BorderWidth = 2;
serie.ShadowOffset = 1;
serie.Points.DataBindXY(times, new[] { data.Select(a => a.Values[i]).ToArray() });
serie.LegendText = measures[i].Type.Name;
serie.Font = new Font(FontFamily.GenericSansSerif, 10, FontStyle.Regular);
chart.Series.Add(serie);
}
}
}
}
this is mainly stream writer method using BuildChart method
public static void SaveChart(System.IO.Stream stream, System.Drawing.Imaging.ImageFormat format, int w, int h, IEnumerable<MultiMeasureData> source, Measure[] measures,bool transparent)
{
var c = new Chart() { Width = w, Height = h};
BuildChart(c, source, measures,transparent);
c.SaveImage(stream, format);
}
And here is both results.
Background.White (transparent parameter is false)
Background.Transparent (transparent parameter is true)
look at this answer :MS Chart Control: Formatting Axis Labels
This solved my problems
Regards
Nemanja
I am trying to reproduce a radar chart in ASP.NET MVC.
This is what I should have
This is what I actually have
So far, it works, the odd colors are just for development.
But the label rotation of the bottom 3 labels is quite bad, and I can't seem to find out how to rotate them properly. Anyone ?
Also, why is it setting markers in a 20 interval step, when I set 25 ?
And addtionally, just for fun, is it possible to rotate the y-axis thick markers by 22.5 degrees, as in the sample ?
Here my code:
using System.Drawing;
using System.Web.UI.DataVisualization.Charting;
// http://stackoverflow.com/questions/6047961/c-sharp-chart-rotate-labels
public FileResult RadarSample()
{
int pixelWidth = 1000;
int pixelHeight = 1000;
// Populate series data
//string[] xValues = { "France", "Canada", "Germany", "USA", "Italy", "Spain", "Russia", "Sweden", "Japan" };
string[] xValues = { "Offene Aussenpolitik", "Liberale Wirtschaftspolitik", "Restriktive Finanzpolitik", "Law & Order", "Restriktive Migrationspolitik", "Ausgebauter Umweltschutz", "Ausgebauter Sozialstaat", "Liberale Gesellschaft" };
double[] yValues = { 80, 90, 45, 75, 37.5, 40, 28, 54 };
//double[] yValues = { 65.62, 75.54, 60.45, 34.73, 85.42, 55.9, 63.6, 55.1, 77.2 };
//double[] yValues2 = { 76.45, 23.78, 86.45, 30.76, 23.79, 35.67, 89.56, 67.45, 38.98 };
var Chart1 = new System.Web.UI.DataVisualization.Charting.Chart();
Chart1.BackColor = System.Drawing.Color.HotPink;
var area = new System.Web.UI.DataVisualization.Charting.ChartArea("ca1");
area.Area3DStyle.Enable3D = false;
area.AxisX.Interval = 1;
area.BackColor = System.Drawing.Color.Red;
//area.AxisY.Interval = 5;
area.AxisY.MajorTickMark.Enabled = false;
area.AxisY.MajorGrid.LineColor = Color.Gray;
area.AxisY.MajorGrid.Interval = 25;
area.AxisY.MinorTickMark.Enabled = false;
area.AxisY.MinorGrid.Interval = 5;
area.AxisY.MinorGrid.LineColor = Color.Yellow;
Chart1.ChartAreas.Add(area);
var series1 = new System.Web.UI.DataVisualization.Charting.Series();
var series2 = new System.Web.UI.DataVisualization.Charting.Series();
series1.Name = "Series1";
series2.Name = "Series2";
//series1.Color = System.Drawing.Color.Yellow;
series1.Color = System.Drawing.Color.FromArgb(100, 0, 0, 255);
//series1.SmartLabelStyle.Enabled = true;
//series1.LabelAngle = 90;
//Legend legend = new Legend();
////legend.Name = "mylegend";
//legend.Title = "Hello world";
//legend.BackColor = Color.Transparent;
//legend.BackColor = Color.Tomato;
//Chart1.Legends.Add(legend);
// series1.Legend = "mylegend";
series1.LegendText = "A";
series2.LegendText = "B";
// series1.Label = "kickme";
// series2.Label = "bar";
//series1.ChartArea = "ca1";
series1.ChartType = System.Web.UI.DataVisualization.Charting.SeriesChartType.Radar;
series2.ChartType = System.Web.UI.DataVisualization.Charting.SeriesChartType.Radar;
series1.ChartArea = "ca1";
series2.ChartArea = "ca1";
Chart1.Series.Add(series1);
//Chart1.Series.Add(series2);
Chart1.Series["Series1"].Points.DataBindXY(xValues, yValues);
//Chart1.Series["Series2"].Points.DataBindXY(xValues, yValues2);
string[] astrRadarStyleList = new string[] { "Area", "Line", "Marker" }; // Fill, Line, or point
string[] astrAreaDrawingStyleList = new string[] { "Circle", "Polygon" }; // Shape
string[] astrLabelStyleList = new string[] { "Circular", "Radial", "Horizontal" };
string strRadarStyle = astrRadarStyleList[0];
string strAreaDrawingStyle = astrAreaDrawingStyleList[0];
string strLabelStyle = astrLabelStyleList[0];
Chart1.Width = System.Web.UI.WebControls.Unit.Pixel(pixelWidth);
Chart1.Height = System.Web.UI.WebControls.Unit.Pixel(pixelHeight);
// Set radar chart style
Chart1.Series["Series1"]["RadarDrawingStyle"] = strRadarStyle; // RadarStyleList.SelectedItem.Text;
//Chart1.Series["Series2"]["RadarDrawingStyle"] = strRadarStyle; // RadarStyleList.SelectedItem.Text;
if (strRadarStyle == "Area")
{
Chart1.Series["Series1"].BorderColor = Color.FromArgb(100, 100, 100);
Chart1.Series["Series1"].BorderWidth = 1;
// Chart1.Series["Series2"].BorderColor = Color.FromArgb(100, 100, 100);
// Chart1.Series["Series2"].BorderWidth = 1;
}
else if (strRadarStyle == "Line")
{
Chart1.Series["Series1"].BorderColor = Color.Empty;
Chart1.Series["Series1"].BorderWidth = 2;
// Chart1.Series["Series2"].BorderColor = Color.Empty;
// Chart1.Series["Series2"].BorderWidth = 2;
}
else if (strRadarStyle == "Marker")
{
Chart1.Series["Series1"].BorderColor = Color.Empty;
// Chart1.Series["Series2"].BorderColor = Color.Empty;
}
// Set circular area drawing style
Chart1.Series["Series1"]["AreaDrawingStyle"] = strAreaDrawingStyle; // AreaDrawingStyleList.SelectedItem.Text;
//Chart1.Series["Series2"]["AreaDrawingStyle"] = strAreaDrawingStyle; // AreaDrawingStyleList.SelectedItem.Text;
// Set labels style
Chart1.Series["Series1"]["CircularLabelsStyle"] = strLabelStyle; // LabelStyleList.SelectedItem.Text;
//Chart1.Series["Series2"]["CircularLabelsStyle"] = strLabelStyle; //LabelStyleList.SelectedItem.Text;
return Chart2Image(Chart1);
}
public FileResult Chart2Image(System.Web.UI.DataVisualization.Charting.Chart chart)
{
using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
{
chart.SaveImage(ms, System.Web.UI.DataVisualization.Charting.ChartImageFormat.Png);
ms.Seek(0, System.IO.SeekOrigin.Begin);
return File(ms.ToArray(), "image/png", "mychart.png");
} // End Using ms
}
Try this for text direction of labels:
Chart1.Series["Series1"]["CircularLabelsStyle"] = "Horizontal";