Does anybody have some experience working with charts in .NET? Specially I want to create them programmatically.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
using System.Diagnostics;
namespace WindowsFormsApplication6
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Random rnd = new Random();
Chart mych = new Chart();
mych.Series.Add("duck");
mych.Series["duck"].SetDefault(true);
mych.Series["duck"].Enabled = true;
mych.Visible = true;
for (int q = 0; q < 10; q++)
{
int first = rnd.Next(0,10);
int second = rnd.Next(0,10);
mych.Series["duck"].Points.AddXY(first, second);
Debug.WriteLine(first + " " + second);
}
mych.Show();
Controls.Add(mych);
mych.Show();
}
}
}
I'm trying to use .NET (.net 4, Visual Studio 2010) chart, but the random generated data set, doesn't appear. The chart remained blank. I searched for examples and only found ones like this , and, yes with manual "drag" method it works. I have no idea why the data I programmatically generate doesn't appear.
Yep.
// FakeChart.cs
// ------------------------------------------------------------------
//
// A Winforms app that produces a contrived chart using
// DataVisualization (MSChart). Requires .net 4.0.
//
// Author: Dino
//
// ------------------------------------------------------------------
//
// compile: \net4.0\csc.exe /t:winexe /debug+ /R:\net4.0\System.Windows.Forms.DataVisualization.dll FakeChart.cs
//
using System;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
namespace Dino.Tools.WebMonitor
{
public class FakeChartForm1 : Form
{
private System.ComponentModel.IContainer components = null;
System.Windows.Forms.DataVisualization.Charting.Chart chart1;
public FakeChartForm1 ()
{
InitializeComponent();
}
private double f(int i)
{
var f1 = 59894 - (8128 * i) + (262 * i * i) - (1.6 * i * i * i);
return f1;
}
private void Form1_Load(object sender, EventArgs e)
{
chart1.Series.Clear();
var series1 = new System.Windows.Forms.DataVisualization.Charting.Series
{
Name = "Series1",
Color = System.Drawing.Color.Green,
IsVisibleInLegend = false,
IsXValueIndexed = true,
ChartType = SeriesChartType.Line
};
this.chart1.Series.Add(series1);
for (int i=0; i < 100; i++)
{
series1.Points.AddXY(i, f(i));
}
chart1.Invalidate();
}
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea1 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
System.Windows.Forms.DataVisualization.Charting.Legend legend1 = new System.Windows.Forms.DataVisualization.Charting.Legend();
this.chart1 = new System.Windows.Forms.DataVisualization.Charting.Chart();
((System.ComponentModel.ISupportInitialize)(this.chart1)).BeginInit();
this.SuspendLayout();
//
// chart1
//
chartArea1.Name = "ChartArea1";
this.chart1.ChartAreas.Add(chartArea1);
this.chart1.Dock = System.Windows.Forms.DockStyle.Fill;
legend1.Name = "Legend1";
this.chart1.Legends.Add(legend1);
this.chart1.Location = new System.Drawing.Point(0, 50);
this.chart1.Name = "chart1";
// this.chart1.Size = new System.Drawing.Size(284, 212);
this.chart1.TabIndex = 0;
this.chart1.Text = "chart1";
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(284, 262);
this.Controls.Add(this.chart1);
this.Name = "Form1";
this.Text = "FakeChart";
this.Load += new System.EventHandler(this.Form1_Load);
((System.ComponentModel.ISupportInitialize)(this.chart1)).EndInit();
this.ResumeLayout(false);
}
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new FakeChartForm1());
}
}
}
UI:
Microsoft has a nice chart control. Download it here. Great video on this here. Example code is here. Happy coding!
Add a reference to System.Windows.Form.DataVisualization, then add the appropriate using statement:
using System.Windows.Forms.DataVisualization.Charting;
private void CreateChart()
{
var series = new Series("Finance");
// Frist parameter is X-Axis and Second is Collection of Y- Axis
series.Points.DataBindXY(new[] { 2001, 2002, 2003, 2004 }, new[] { 100, 200, 90, 150 });
chart1.Series.Add(series);
}
Try to include these lines on your code, after mych.Visible = true;:
ChartArea chA = new ChartArea();
mych.ChartAreas.Add(chA);
You need to attach the Form1_Load handler to the Load event:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
using System.Diagnostics;
namespace WindowsFormsApplication6
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Load += Form1_Load;
}
private void Form1_Load(object sender, EventArgs e)
{
Random rnd = new Random();
Chart mych = new Chart();
mych.Height = 100;
mych.Width = 100;
mych.BackColor = SystemColors.Highlight;
mych.Series.Add("duck");
mych.Series["duck"].SetDefault(true);
mych.Series["duck"].Enabled = true;
mych.Visible = true;
for (int q = 0; q < 10; q++)
{
int first = rnd.Next(0, 10);
int second = rnd.Next(0, 10);
mych.Series["duck"].Points.AddXY(first, second);
Debug.WriteLine(first + " " + second);
}
Controls.Add(mych);
}
}
}
Related
I'm trying to build a Russian Roulette style program where you click a button and it randomly selects one of 25 images to display on screen but I can't seem to figure out how to call the images using the generator.
It works fine when I select an image manually, as seen in my code below, but anything else seems to return an error.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Timers;
using System.Threading.Tasks;
using System.IO;
using System.Windows.Forms;
using System.Security.Cryptography;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void label_click(object sender, EventArgs e)
{
Close();
}
int mouseX = 0, mouseY = 0;
bool mouseDown;
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
mouseDown = true;
}
private void panel1_MouseUp(object sender, MouseEventArgs e)
{
mouseDown = false;
}
private void GOBUTN_Paint(object sender, PaintEventArgs e)
{
}
//Sharing is caring: Communism goes here
private System.Windows.Forms.Timer timtim;
int rand0;
PictureBox Rooskie = new PictureBox();
Label test = new Label();
Random rando = new Random();
List<int> duplicheck = new List<int>();
private void boopthesnoot(object sender, EventArgs e)
{
dingding:
//Hell yeah, random numbers here
rand0 = rando.Next(1, 26);
/*string combowombo = string.Join(", ", duplicheck.ToArray());
test.Text = combowombo;
test.Font = new Font("Calibri", 20);
Controls.Add(test);
test.Location = new Point(0, 200);
test.Height = 1000;
test.Width = 1000;*/
if(duplicheck.Contains(rand0))
{
goto dingding;
}
else
{
GOBUTTON.Hide();
pictureBox1.Hide();
pictureBox2.Hide();
//Fuckin image code goes here my dood
Rooskie.Width = 1160;
Rooskie.Height = 620;
Bitmap image = new Bitmap(WindowsFormsApp1.Properties.Resources._1);
Rooskie.Dock = DockStyle.Fill;
Rooskie.Image = (Image)image;
Controls.Add(Rooskie);
Rooskie.SizeMode = PictureBoxSizeMode.CenterImage;
//Aww shit, it's that timer time
timtim = new System.Windows.Forms.Timer();
timtim.Tick += new EventHandler(clockfinish);
timtim.Interval = 3000;
timtim.Start();
duplicheck.Add(rand0);
if (duplicheck.Count == 25)
{
duplicheck = new List<int>();
}
}
}
private void clockfinish(object sender, EventArgs e)
{
//CEASE THE TIMER AND GIVE ME BACK MY BUTTON
Rooskie.Image = null;
timtim.Stop();
GOBUTTON.Show();
pictureBox1.Show();
pictureBox2.Show();
}
The expected result is when the user presses the button it calls up the image without having to load it from a folder.
I'm trying to exclude old results from a random number generator but I can't seem to get the variables to remember past two. I'm new to C# so there's probably some really simple solution I'm overlooking. It'd be super helpful if you guys could enlighten me.
I've already tried the code shown below, and I'm fairly sure I'm being stupid but I can't figure out why it's not working.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Timers;
using System.Threading.Tasks;
using System.IO;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void label_click(object sender, EventArgs e)
{
Close();
}
int mouseX = 0, mouseY = 0;
bool mouseDown;
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
mouseDown = true;
}
private void panel1_MouseUp(object sender, MouseEventArgs e)
{
mouseDown = false;
}
private void GOBUTN_Paint(object sender, PaintEventArgs e)
{
}
//Sharing is caring: Communism goes here
private System.Windows.Forms.Timer timtim;
PictureBox Rooskie = new PictureBox();
int duplicheck = 0;
int duplicheck2 = 0;
int duplicheck3 = 0;
Label test = new Label();
private void boopthesnoot(object sender, EventArgs e)
{
dinging:
//yeah, random numbers here
Random rando = new Random();
int rand0 = rando.Next(1, 25);
test.Text = duplicheck + ", " + duplicheck2 + ", " + duplicheck3;
test.Font = new Font("Calibri", 20);
Controls.Add(test);
test.Location = new Point(0, 200);
test.Height = 1000;
test.Width = 1000;
if(duplicheck != rand0 && duplicheck2 != rand0 && duplicheck3 != rand0)
{
GOBUTTON.Hide();
pictureBox1.Hide();
pictureBox2.Hide();
//image code goes here
string filepath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\" + "resources" + "\\" + rand0 + ".jpg";
Rooskie.Width = 1160;
Rooskie.Height = 620;
Bitmap image = new Bitmap(filepath);
Rooskie.Dock = DockStyle.Fill;
Rooskie.Image = (Image)image;
Controls.Add(Rooskie);
Rooskie.SizeMode = PictureBoxSizeMode.CenterImage;
//Aww, it's that timer time
timtim = new System.Windows.Forms.Timer();
timtim.Tick += new EventHandler(clockfinish);
timtim.Interval = 5000;
timtim.Start();
}
else
{
goto dinging;
}
if (duplicheck != rand0)
{
duplicheck2 = duplicheck;
}
if(duplicheck != rand0)
{
duplicheck2 = duplicheck;
}
if (duplicheck2 != duplicheck)
{
duplicheck3 = duplicheck2;
}
duplicheck = rand0;
}
private void clockfinish(object sender, EventArgs e)
{
//CEASE THE TIMER AND GIVE ME BACK MY BUTTON
Rooskie.Image = null;
timtim.Stop();
GOBUTTON.Show();
pictureBox1.Show();
pictureBox2.Show();
}
The idea is that a random number generator picks an image and displays it. But I don't want the same image to show up multiple times in a row so this is supposed to give it a buffer i.e. If image 2 was displayed on the first button press, image 1 was displayed on the second, and image 3 was displayed on the third, the results should look like: duplicheck = 2 duplicheck2 = 1 duplicheck3 = 3
So with the help of everyone in the comments and a lot of messing around I wound up with this. It works perfectly to prevent any image from being displayed more than once per 25 clicks of the button. Thank you guys so much for the help on this! I don't think I'd have figured this out without you.
//Sharing is caring: Communism goes here
private System.Windows.Forms.Timer timtim;
int rand0;
PictureBox Rooskie = new PictureBox();
Label test = new Label();
Random rando = new Random();
List<int> duplicheck = new List<int>();
private void boopthesnoot(object sender, EventArgs e)
{
dingding:
//yeah, random numbers here
rand0 = rando.Next(1, 26);
/*string combowombo = string.Join(", ", duplicheck.ToArray());
test.Text = combowombo;
test.Font = new Font("Calibri", 20);
Controls.Add(test);
test.Location = new Point(0, 200);
test.Height = 1000;
test.Width = 1000;*/
if(duplicheck.Contains(rand0))
{
goto dingding;
}
else
{
GOBUTTON.Hide();
pictureBox1.Hide();
pictureBox2.Hide();
//image code goes here
Rooskie.Width = 1160;
Rooskie.Height = 620;
Bitmap image = new Bitmap(WindowsFormsApp1.Properties.Resources._1);
Rooskie.Dock = DockStyle.Fill;
Rooskie.Image = (Image)image;
Controls.Add(Rooskie);
Rooskie.SizeMode = PictureBoxSizeMode.CenterImage;
//Aww, it's that timer time
timtim = new System.Windows.Forms.Timer();
timtim.Tick += new EventHandler(clockfinish);
timtim.Interval = 3000;
timtim.Start();
duplicheck.Add(rand0);
if (duplicheck.Count == 25)
{
duplicheck = new List<int>();
}
}
}
When working on an application i decide to add my first user control for that project. I make it just fine, however when i drag it in to my main form from the toolbox it pops up with an error message:
No matter what i do it doesn't seem to fix it. I have tried adding it through code however it simply wouldn't show up at all.
Looking in to the problem online I was not able to find a working solution, or at least no solution that I could follow and understand.
Help would really be appreciated, and if any more information is needed I would be glad to add it. However currently I don't know what I could add that could be of any use.
The code is for a simple prank virus (Have to inspire myself to keep learning to code :) ) Here is the code (Please don't launch the file, it is a prank virus after all, the only way to exit is alt+f4):
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Simple_virus_V2
{
public partial class Form1 : Form
{
[DllImport("user32.dll")]
internal static extern IntPtr SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
internal static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
public Form1()
{
InitializeComponent();
timer1.Start();
timer2.Start();
Thread newthread = new Thread(progress);
newthread.Start();
}
Random rnd = new Random();
int noticewidth = 0;
bool changecursor = false;
private void progress() {
Thread.Sleep(1000);
changecursor = true;
Thread.Sleep(1000);
timer3.Start();
Thread.Sleep(5000);
noticewidth = Width;
}
int mouseflash = 0;
private void timer1_Tick(object sender, EventArgs e)
{
if (changecursor) {
if (mouseflash < 1000)
{
Bitmap cursor = new Bitmap(new Bitmap(pictureBox1.Image), 24, 24);
Cursor = new Cursor(cursor.GetHicon());
} else if (mouseflash < 1700) {
Bitmap cursor = new Bitmap(new Bitmap(pictureBox2.Image), 30, 30);
Cursor = new Cursor(cursor.GetHicon());
}
else {
mouseflash = 0;
}
mouseflash = mouseflash + rnd.Next(3,10);
}
header.Left = MousePosition.X - (header.Width / 2);
label2.Left = MousePosition.X - (label2.Width / 2);
label3.Left = label2.Left + 25;
panel1.Width = noticewidth;
this.Location = new Point(0,0);
panel1.Location = new Point(0, MousePosition.Y - 40);
this.WindowState = FormWindowState.Maximized;
TopMost = true;
Process currentProcess = Process.GetCurrentProcess();
IntPtr hWnd = currentProcess.MainWindowHandle;
if (hWnd != IntPtr.Zero)
{
SetForegroundWindow(hWnd);
ShowWindow(hWnd, int.Parse("9"));
}
Focus();
this.Width = Screen.PrimaryScreen.Bounds.Width * 3;
this.Height = Screen.PrimaryScreen.Bounds.Height * 2;
}
private void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
/*
using (Form1 frm = new Form1()) {
if (frm.ShowDialog() == DialogResult.OK) {
}
}
*/
}
private void timer2_Tick(object sender, EventArgs e)
{
PictureBox pic = new PictureBox();
pic.Width = 1;
pic.Height = 1;
pic.BackColor = Color.Black;
pic.Location = new Point(rnd.Next(0, this.Width), rnd.Next(0, this.Height));
this.Controls.Add(pic);
}
private void timer3_Tick(object sender, EventArgs e)
{
/*
bartry bars = new bartry();
bars.Location = new Point(0, rnd.Next(0, 500));
Controls.Add(bars);
timer3.Interval = rnd.Next(100, 5000);
*/
}
}
}
Thanks
After ages of trying out the answers on the other post none of them ended up working. I did find the solution after opening a new project and experimenting around with my code.
The solution: Make sure that the user control and the main forms have the same "using" references!
Sorry if this was self explanatory, but i didn't know that you had to do that.
Just debug the project then try to add the User control form
I keep getting this error when trying to initialise the form with my graph on it. Can't figure out a work around for it. Think it has something to do with Data Binding
Any ideas ?
Here is my code -
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
namespace NoCAnalysisTool2
{
public partial class Visualisation : UserControl
{
public string tx_graph { get; set; }
public List<int> tx_graphData { get; set; }
public Visualisation(string txGraph, List<int> tx_GData)
{
InitializeComponent();
tx_graph = txGraph;
tx_graphData = tx_GData;
// Set 3D chart settings
chart1.ChartAreas["Default"].Area3DStyle.Enable3D = true;
chart1.ChartAreas["Default"].Area3DStyle.IsRightAngleAxes = false;
chart1.ChartAreas["Default"].Area3DStyle.Inclination = 40;
chart1.ChartAreas["Default"].Area3DStyle.Rotation = 20;
chart1.ChartAreas["Default"].Area3DStyle.LightStyle = LightStyle.Realistic;
// Populate series with random data
Random random = new Random();
for (int pointIndex = 0; pointIndex < 10; pointIndex++)
{
chart1.Series["Series1"].Points.AddY(random.Next(45, 95));
chart1.Series["Series2"].Points.AddY(random.Next(5, 75));
}
// Set series chart type
chart1.Series["Series1"].ChartType = SeriesChartType.Line;
chart1.Series["Series2"].ChartType = SeriesChartType.Spline;
// Set point labels
chart1.Series["Series1"].IsValueShownAsLabel = true;
chart1.Series["Series2"].IsValueShownAsLabel = true;
// Enable X axis margin
chart1.ChartAreas["Default"].AxisX.IsMarginVisible = true;
// Enable the ShowMarkerLines
chart1.Series["Series1"]["ShowMarkerLines"] = "true";
chart1.Series["Series2"]["ShowMarkerLines"] = "true";
}
private void TxGraph_Load(object sender, EventArgs e)
{
}
private void Tx_graph_Click(object sender, EventArgs e)
{
}
private void Visualisation_Load(object sender, EventArgs e)
{
}
private void chart11_Click(object sender, EventArgs e)
{
}
}
}
The 'default' ChartArea is not called "Default" but "ChartArea1".
Trying to access an indexer by a wrong name results in an Argument Exeption.
You have the choice of either calling it by its index:
ChartArea ca = chart1.ChartAreas[0];
Or by its right name:
ChartArea ca = chart1.ChartAreas["ChartArea1"];
Or set the Name property th a string you like..:
chart1.ChartAreas[0].Name = "Default";
..and then calli it by that Name:
chart1.ChartAreas["Default"].Area3DStyle.Enable3D = true;
Btw: I hope you have added the 2nd Series in the designer and given it the right Name ;-)
I just can't find a solution for changing the format of the y-axis tick labels.
Now I get labels like 0.03 and 0.035. But I always need three digits behind the decimal point.
The big question is, how to access the label format?
This is my code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Media;
using LiveCharts;
using LiveCharts.Helpers;
using LiveCharts.Wpf;
using LiveCharts.Wpf.Charts.Base;
using Brushes = System.Windows.Media.Brushes;
using Color = System.Windows.Media.Color;
using MessageBox = System.Windows.Forms.MessageBox;
namespace LiveAnalysis
{
public partial class Form1 : Form
{
List<DateTime> xvals = new List<DateTime>();
List<double> yvals = new List<double>();
private int _amountValues;
private int _startValue;
private List<double> _yvalsRange;
public Form1()
{
InitializeComponent();
// event
cartesianChart2.DataClick += CartesianChart1OnDataClick;
hScrollBar1.ValueChanged += (sender, e) => hScrollBar1_ValueChange(sender, e, hScrollBar1.Value);
// get original data
using (var db = new Analysis.DataClasses1DataContext())
{
var lttResults = db.LttResults;
var par1 = 0.0;
foreach (var data in lttResults)
{
if (data.GatewayEventType == 41)
par1 = data.FloatValue;
if (data.GatewayEventType != 42) continue;
var par2 = data.FloatValue;
var diff = Math.Round(par1 - par2, 3);
yvals.Add(diff);
xvals.Add(data.DateTime);
}
}
// chart settings
ChartSettings();
}
private void ChartSettings()
{
// performance
cartesianChart2.DisableAnimations = true;
cartesianChart2.DataTooltip = null;
cartesianChart2.Hoverable = false;
_startValue = 0;
_amountValues = 400;
_yvalsRange = yvals.GetRange(_startValue, _startValue + _amountValues);
// series setting
ScatterSeries scatterSeries1 = new ScatterSeries("Series1");
cartesianChart2.Series.Add(scatterSeries1);
scatterSeries1.Values = _yvalsRange.AsChartValues();
scatterSeries1.MaxPointShapeDiameter = 10;
scatterSeries1.Title = "Series1";
cartesianChart2.AxisX.Add(new Axis
{
Name = "xAxis",
Title = "DateTime",
FontSize = 22,
Foreground = System.Windows.Media.Brushes.Black,
MinValue = 0,
MaxValue = _amountValues,
});
cartesianChart2.AxisY.Add(new Axis
{
Name = "yAxis",
Title = "Time difference",
FontSize = 22,
Foreground = System.Windows.Media.Brushes.Black,
MinValue = -0.025,
MaxValue = 0.04,
});
}
private void CartesianChart1OnDataClick(object sender, ChartPoint chartPoint)
{
label1.Text = $#"You clicked: {chartPoint.X},{chartPoint.Y}";
}
private void button2_Click_1(object sender, EventArgs e)
{
}
private void hScrollBar1_ValueChange(object sender, EventArgs e, int value)
{
RedrawGraph(value);
}
private void RedrawGraph(int value)
{
_startValue = value * 10;
_yvalsRange = yvals.GetRange(_startValue, _startValue + _amountValues);
cartesianChart2.Series[0].Values = _yvalsRange.AsChartValues();
cartesianChart2.AxisX[0].MinValue = _startValue;
cartesianChart2.AxisX[0].MaxValue = _startValue + _amountValues;
}
}
}
The answer is:
Func<double, string> formatFunc = (x) => string.Format("{0:0.000}", x);
cartesianChart2.AxisY.Add(new Axis
{
LabelFormatter = formatFunc,
});