What's the best way to draw chart with discrete values on Canvas?












0














I have a Canvas with dynamic width. I need to draw a chart on this Canvas. Due to the amount of the measured values and the business area specificity it's not possible to use third-party controls and components.



The chart shows the level of some measurement that is discrete. The X axis indicates the time of the measurement. In the worst case every pixel of the chart can have different level. So it looks like this:
Chart



My first approach just to make it working was to draw a line for every pixel. So my code looks like this:



        MyCanvas.Children.Clear();
var random = new Random();
for (var i = 0; i < MyCanvas.Width; i++)
{
var line = new Line()
{
X1 = i,
X2 = i,
Y1 = MyCanvas.ActualHeight,
Y2 = MyCanvas.ActualHeight - random.Next(0, (int)MyCanvas.ActualHeight),
Stroke = Brushes.Blue
};

MyCanvas.Children.Add(line);
}


This code does what I want it to do. It draws a chart like this one:
Chart



But it seems that it is not an optimal way to do things like this one. My chart should support panning and zooming and it takes around 200-350ms to redraw a chart on every user request. That's too much (1000/350 = 2.85fps).



I don't have much experience in WPF so my question is - what is the most optimal way to draw such chart? Maybe I need to use Paths and Geometry objects but I can't say for sure that it will give much perfomance gain until I implement it. Also I don't know what kind of Geometry I need to use. It seems that LineGeometry matches my expectations.



Thanks in advance.










share|improve this question






















  • How many points do you need? You shouldn't draw every point, but only a fixed number of points. If you have more points than you can draw then you can use math functions for approximating shape of the data.
    – FCin
    21 hours ago










  • @FCin , the number of points is equal to MyCanvas.Width
    – Dobby007
    20 hours ago












  • Take a look at msdn.microsoft.com/en-us/magazine/…
    – Andy
    16 hours ago
















0














I have a Canvas with dynamic width. I need to draw a chart on this Canvas. Due to the amount of the measured values and the business area specificity it's not possible to use third-party controls and components.



The chart shows the level of some measurement that is discrete. The X axis indicates the time of the measurement. In the worst case every pixel of the chart can have different level. So it looks like this:
Chart



My first approach just to make it working was to draw a line for every pixel. So my code looks like this:



        MyCanvas.Children.Clear();
var random = new Random();
for (var i = 0; i < MyCanvas.Width; i++)
{
var line = new Line()
{
X1 = i,
X2 = i,
Y1 = MyCanvas.ActualHeight,
Y2 = MyCanvas.ActualHeight - random.Next(0, (int)MyCanvas.ActualHeight),
Stroke = Brushes.Blue
};

MyCanvas.Children.Add(line);
}


This code does what I want it to do. It draws a chart like this one:
Chart



But it seems that it is not an optimal way to do things like this one. My chart should support panning and zooming and it takes around 200-350ms to redraw a chart on every user request. That's too much (1000/350 = 2.85fps).



I don't have much experience in WPF so my question is - what is the most optimal way to draw such chart? Maybe I need to use Paths and Geometry objects but I can't say for sure that it will give much perfomance gain until I implement it. Also I don't know what kind of Geometry I need to use. It seems that LineGeometry matches my expectations.



Thanks in advance.










share|improve this question






















  • How many points do you need? You shouldn't draw every point, but only a fixed number of points. If you have more points than you can draw then you can use math functions for approximating shape of the data.
    – FCin
    21 hours ago










  • @FCin , the number of points is equal to MyCanvas.Width
    – Dobby007
    20 hours ago












  • Take a look at msdn.microsoft.com/en-us/magazine/…
    – Andy
    16 hours ago














0












0








0


1





I have a Canvas with dynamic width. I need to draw a chart on this Canvas. Due to the amount of the measured values and the business area specificity it's not possible to use third-party controls and components.



The chart shows the level of some measurement that is discrete. The X axis indicates the time of the measurement. In the worst case every pixel of the chart can have different level. So it looks like this:
Chart



My first approach just to make it working was to draw a line for every pixel. So my code looks like this:



        MyCanvas.Children.Clear();
var random = new Random();
for (var i = 0; i < MyCanvas.Width; i++)
{
var line = new Line()
{
X1 = i,
X2 = i,
Y1 = MyCanvas.ActualHeight,
Y2 = MyCanvas.ActualHeight - random.Next(0, (int)MyCanvas.ActualHeight),
Stroke = Brushes.Blue
};

MyCanvas.Children.Add(line);
}


This code does what I want it to do. It draws a chart like this one:
Chart



But it seems that it is not an optimal way to do things like this one. My chart should support panning and zooming and it takes around 200-350ms to redraw a chart on every user request. That's too much (1000/350 = 2.85fps).



I don't have much experience in WPF so my question is - what is the most optimal way to draw such chart? Maybe I need to use Paths and Geometry objects but I can't say for sure that it will give much perfomance gain until I implement it. Also I don't know what kind of Geometry I need to use. It seems that LineGeometry matches my expectations.



Thanks in advance.










share|improve this question













I have a Canvas with dynamic width. I need to draw a chart on this Canvas. Due to the amount of the measured values and the business area specificity it's not possible to use third-party controls and components.



The chart shows the level of some measurement that is discrete. The X axis indicates the time of the measurement. In the worst case every pixel of the chart can have different level. So it looks like this:
Chart



My first approach just to make it working was to draw a line for every pixel. So my code looks like this:



        MyCanvas.Children.Clear();
var random = new Random();
for (var i = 0; i < MyCanvas.Width; i++)
{
var line = new Line()
{
X1 = i,
X2 = i,
Y1 = MyCanvas.ActualHeight,
Y2 = MyCanvas.ActualHeight - random.Next(0, (int)MyCanvas.ActualHeight),
Stroke = Brushes.Blue
};

MyCanvas.Children.Add(line);
}


This code does what I want it to do. It draws a chart like this one:
Chart



But it seems that it is not an optimal way to do things like this one. My chart should support panning and zooming and it takes around 200-350ms to redraw a chart on every user request. That's too much (1000/350 = 2.85fps).



I don't have much experience in WPF so my question is - what is the most optimal way to draw such chart? Maybe I need to use Paths and Geometry objects but I can't say for sure that it will give much perfomance gain until I implement it. Also I don't know what kind of Geometry I need to use. It seems that LineGeometry matches my expectations.



Thanks in advance.







c# wpf performance canvas charts






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked 21 hours ago









Dobby007

6311818




6311818












  • How many points do you need? You shouldn't draw every point, but only a fixed number of points. If you have more points than you can draw then you can use math functions for approximating shape of the data.
    – FCin
    21 hours ago










  • @FCin , the number of points is equal to MyCanvas.Width
    – Dobby007
    20 hours ago












  • Take a look at msdn.microsoft.com/en-us/magazine/…
    – Andy
    16 hours ago


















  • How many points do you need? You shouldn't draw every point, but only a fixed number of points. If you have more points than you can draw then you can use math functions for approximating shape of the data.
    – FCin
    21 hours ago










  • @FCin , the number of points is equal to MyCanvas.Width
    – Dobby007
    20 hours ago












  • Take a look at msdn.microsoft.com/en-us/magazine/…
    – Andy
    16 hours ago
















How many points do you need? You shouldn't draw every point, but only a fixed number of points. If you have more points than you can draw then you can use math functions for approximating shape of the data.
– FCin
21 hours ago




How many points do you need? You shouldn't draw every point, but only a fixed number of points. If you have more points than you can draw then you can use math functions for approximating shape of the data.
– FCin
21 hours ago












@FCin , the number of points is equal to MyCanvas.Width
– Dobby007
20 hours ago






@FCin , the number of points is equal to MyCanvas.Width
– Dobby007
20 hours ago














Take a look at msdn.microsoft.com/en-us/magazine/…
– Andy
16 hours ago




Take a look at msdn.microsoft.com/en-us/magazine/…
– Andy
16 hours ago












1 Answer
1






active

oldest

votes


















0














Very easy to do, but I'd strongly recommend you use data binding.




  1. Create an ItemsControl.

  2. Give the ItemsControl an ItemsPanel of type Canvas.

  3. Bind the Canvas Width and Height to elements in your view model specifying the extents of each axis.

  4. Wrap the whole thing in a Viewbox so that it scales automatically, irrespective of width and height.

  5. For each element in your ItemsControl list create a view model containing X1/Y1/X2/Y2, then use a DataTemplate to render those items using those values to draw a vertical line.


So basically your main view model should look something like this (which by way of demonstration is generating random data points):



public class MainViewModel : ObservableObject
{
private IEnumerable<DataPointViewModel> _DataPoints;
public IEnumerable<DataPointViewModel> DataPoints
{
get { return this._DataPoints; }
set { Set(() => this.DataPoints, ref this._DataPoints, value); }
}

public int ChartWidth { get; } = 1000;
public int ChartHeight { get; } = 1000;

public MainViewModel()
{
var rng = new Random();
this.DataPoints = Enumerable.Range(0, this.ChartWidth)
.Select(x => new DataPointViewModel {X1 = x, Y1 = this.ChartHeight-1, X2 = x, Y2 = this.ChartHeight - 1 - rng.Next(this.ChartHeight) });
}
}


The view model for the items in your collection need to provide the points for the line that is used to render them:



public class DataPointViewModel : ObservableObject
{
private double _X1;
public double X1
{
get { return this._X1; }
set { Set(() => this.X1, ref this._X1, value); }
}

private double _Y1;
public double Y1
{
get { return this._Y1; }
set { Set(() => this.Y1, ref this._Y1, value); }
}

private double _X2;
public double X2
{
get { return this._X2; }
set { Set(() => this.X2, ref this._X2, value); }
}

private double _Y2;
public double Y2
{
get { return this._Y2; }
set { Set(() => this.Y2, ref this._Y2, value); }
}
}


And then your XAML simply uses these to render a line for each data point on a Canvas control:



<Viewbox>
<ItemsControl ItemsSource="{Binding DataPoints}" Width="{Binding ChartWidth}" Height="{Binding ChartHeight}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Line Stroke="Blue" StrokeThickness="1" X1="{Binding X1}" Y1="{Binding Y1}" X2="{Binding X2}" Y2="{Binding Y2}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Viewbox>


This will all in turn generate the following output:



enter image description here






share|improve this answer





















  • I must mention that I have huge collection of 'DataPoints' so in your solution I need to update DataPoints property constantly Have you compared the performance of constant updating of DataPoints property to the performance of simple Canvas redrawing? I want to keep update rate of the chart around 60fps when user scrolls it. I think that ItemsControl uses the same Add method on Canvas. Am I wrong? I wanted to run your example locally to measure it by myself but I can't find your implementation of ObservableObject anywhere in the internet.
    – Dobby007
    18 hours ago










  • Ah, that's a pretty important detail. In this case I probably wouldn't use WPF, high performance was never one of its primary design features.
    – Mark Feldman
    8 hours ago










  • ObservableObject is part of MVVM Light, you could use ViewModelBase instead or indeed anything else that support INPC. But yeah, if you need real-time high performance then forget data-binding, you're probably going to have to resort to DirectX or something.
    – Mark Feldman
    8 hours ago













Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53942844%2fwhats-the-best-way-to-draw-chart-with-discrete-values-on-canvas%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









0














Very easy to do, but I'd strongly recommend you use data binding.




  1. Create an ItemsControl.

  2. Give the ItemsControl an ItemsPanel of type Canvas.

  3. Bind the Canvas Width and Height to elements in your view model specifying the extents of each axis.

  4. Wrap the whole thing in a Viewbox so that it scales automatically, irrespective of width and height.

  5. For each element in your ItemsControl list create a view model containing X1/Y1/X2/Y2, then use a DataTemplate to render those items using those values to draw a vertical line.


So basically your main view model should look something like this (which by way of demonstration is generating random data points):



public class MainViewModel : ObservableObject
{
private IEnumerable<DataPointViewModel> _DataPoints;
public IEnumerable<DataPointViewModel> DataPoints
{
get { return this._DataPoints; }
set { Set(() => this.DataPoints, ref this._DataPoints, value); }
}

public int ChartWidth { get; } = 1000;
public int ChartHeight { get; } = 1000;

public MainViewModel()
{
var rng = new Random();
this.DataPoints = Enumerable.Range(0, this.ChartWidth)
.Select(x => new DataPointViewModel {X1 = x, Y1 = this.ChartHeight-1, X2 = x, Y2 = this.ChartHeight - 1 - rng.Next(this.ChartHeight) });
}
}


The view model for the items in your collection need to provide the points for the line that is used to render them:



public class DataPointViewModel : ObservableObject
{
private double _X1;
public double X1
{
get { return this._X1; }
set { Set(() => this.X1, ref this._X1, value); }
}

private double _Y1;
public double Y1
{
get { return this._Y1; }
set { Set(() => this.Y1, ref this._Y1, value); }
}

private double _X2;
public double X2
{
get { return this._X2; }
set { Set(() => this.X2, ref this._X2, value); }
}

private double _Y2;
public double Y2
{
get { return this._Y2; }
set { Set(() => this.Y2, ref this._Y2, value); }
}
}


And then your XAML simply uses these to render a line for each data point on a Canvas control:



<Viewbox>
<ItemsControl ItemsSource="{Binding DataPoints}" Width="{Binding ChartWidth}" Height="{Binding ChartHeight}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Line Stroke="Blue" StrokeThickness="1" X1="{Binding X1}" Y1="{Binding Y1}" X2="{Binding X2}" Y2="{Binding Y2}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Viewbox>


This will all in turn generate the following output:



enter image description here






share|improve this answer





















  • I must mention that I have huge collection of 'DataPoints' so in your solution I need to update DataPoints property constantly Have you compared the performance of constant updating of DataPoints property to the performance of simple Canvas redrawing? I want to keep update rate of the chart around 60fps when user scrolls it. I think that ItemsControl uses the same Add method on Canvas. Am I wrong? I wanted to run your example locally to measure it by myself but I can't find your implementation of ObservableObject anywhere in the internet.
    – Dobby007
    18 hours ago










  • Ah, that's a pretty important detail. In this case I probably wouldn't use WPF, high performance was never one of its primary design features.
    – Mark Feldman
    8 hours ago










  • ObservableObject is part of MVVM Light, you could use ViewModelBase instead or indeed anything else that support INPC. But yeah, if you need real-time high performance then forget data-binding, you're probably going to have to resort to DirectX or something.
    – Mark Feldman
    8 hours ago


















0














Very easy to do, but I'd strongly recommend you use data binding.




  1. Create an ItemsControl.

  2. Give the ItemsControl an ItemsPanel of type Canvas.

  3. Bind the Canvas Width and Height to elements in your view model specifying the extents of each axis.

  4. Wrap the whole thing in a Viewbox so that it scales automatically, irrespective of width and height.

  5. For each element in your ItemsControl list create a view model containing X1/Y1/X2/Y2, then use a DataTemplate to render those items using those values to draw a vertical line.


So basically your main view model should look something like this (which by way of demonstration is generating random data points):



public class MainViewModel : ObservableObject
{
private IEnumerable<DataPointViewModel> _DataPoints;
public IEnumerable<DataPointViewModel> DataPoints
{
get { return this._DataPoints; }
set { Set(() => this.DataPoints, ref this._DataPoints, value); }
}

public int ChartWidth { get; } = 1000;
public int ChartHeight { get; } = 1000;

public MainViewModel()
{
var rng = new Random();
this.DataPoints = Enumerable.Range(0, this.ChartWidth)
.Select(x => new DataPointViewModel {X1 = x, Y1 = this.ChartHeight-1, X2 = x, Y2 = this.ChartHeight - 1 - rng.Next(this.ChartHeight) });
}
}


The view model for the items in your collection need to provide the points for the line that is used to render them:



public class DataPointViewModel : ObservableObject
{
private double _X1;
public double X1
{
get { return this._X1; }
set { Set(() => this.X1, ref this._X1, value); }
}

private double _Y1;
public double Y1
{
get { return this._Y1; }
set { Set(() => this.Y1, ref this._Y1, value); }
}

private double _X2;
public double X2
{
get { return this._X2; }
set { Set(() => this.X2, ref this._X2, value); }
}

private double _Y2;
public double Y2
{
get { return this._Y2; }
set { Set(() => this.Y2, ref this._Y2, value); }
}
}


And then your XAML simply uses these to render a line for each data point on a Canvas control:



<Viewbox>
<ItemsControl ItemsSource="{Binding DataPoints}" Width="{Binding ChartWidth}" Height="{Binding ChartHeight}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Line Stroke="Blue" StrokeThickness="1" X1="{Binding X1}" Y1="{Binding Y1}" X2="{Binding X2}" Y2="{Binding Y2}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Viewbox>


This will all in turn generate the following output:



enter image description here






share|improve this answer





















  • I must mention that I have huge collection of 'DataPoints' so in your solution I need to update DataPoints property constantly Have you compared the performance of constant updating of DataPoints property to the performance of simple Canvas redrawing? I want to keep update rate of the chart around 60fps when user scrolls it. I think that ItemsControl uses the same Add method on Canvas. Am I wrong? I wanted to run your example locally to measure it by myself but I can't find your implementation of ObservableObject anywhere in the internet.
    – Dobby007
    18 hours ago










  • Ah, that's a pretty important detail. In this case I probably wouldn't use WPF, high performance was never one of its primary design features.
    – Mark Feldman
    8 hours ago










  • ObservableObject is part of MVVM Light, you could use ViewModelBase instead or indeed anything else that support INPC. But yeah, if you need real-time high performance then forget data-binding, you're probably going to have to resort to DirectX or something.
    – Mark Feldman
    8 hours ago
















0












0








0






Very easy to do, but I'd strongly recommend you use data binding.




  1. Create an ItemsControl.

  2. Give the ItemsControl an ItemsPanel of type Canvas.

  3. Bind the Canvas Width and Height to elements in your view model specifying the extents of each axis.

  4. Wrap the whole thing in a Viewbox so that it scales automatically, irrespective of width and height.

  5. For each element in your ItemsControl list create a view model containing X1/Y1/X2/Y2, then use a DataTemplate to render those items using those values to draw a vertical line.


So basically your main view model should look something like this (which by way of demonstration is generating random data points):



public class MainViewModel : ObservableObject
{
private IEnumerable<DataPointViewModel> _DataPoints;
public IEnumerable<DataPointViewModel> DataPoints
{
get { return this._DataPoints; }
set { Set(() => this.DataPoints, ref this._DataPoints, value); }
}

public int ChartWidth { get; } = 1000;
public int ChartHeight { get; } = 1000;

public MainViewModel()
{
var rng = new Random();
this.DataPoints = Enumerable.Range(0, this.ChartWidth)
.Select(x => new DataPointViewModel {X1 = x, Y1 = this.ChartHeight-1, X2 = x, Y2 = this.ChartHeight - 1 - rng.Next(this.ChartHeight) });
}
}


The view model for the items in your collection need to provide the points for the line that is used to render them:



public class DataPointViewModel : ObservableObject
{
private double _X1;
public double X1
{
get { return this._X1; }
set { Set(() => this.X1, ref this._X1, value); }
}

private double _Y1;
public double Y1
{
get { return this._Y1; }
set { Set(() => this.Y1, ref this._Y1, value); }
}

private double _X2;
public double X2
{
get { return this._X2; }
set { Set(() => this.X2, ref this._X2, value); }
}

private double _Y2;
public double Y2
{
get { return this._Y2; }
set { Set(() => this.Y2, ref this._Y2, value); }
}
}


And then your XAML simply uses these to render a line for each data point on a Canvas control:



<Viewbox>
<ItemsControl ItemsSource="{Binding DataPoints}" Width="{Binding ChartWidth}" Height="{Binding ChartHeight}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Line Stroke="Blue" StrokeThickness="1" X1="{Binding X1}" Y1="{Binding Y1}" X2="{Binding X2}" Y2="{Binding Y2}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Viewbox>


This will all in turn generate the following output:



enter image description here






share|improve this answer












Very easy to do, but I'd strongly recommend you use data binding.




  1. Create an ItemsControl.

  2. Give the ItemsControl an ItemsPanel of type Canvas.

  3. Bind the Canvas Width and Height to elements in your view model specifying the extents of each axis.

  4. Wrap the whole thing in a Viewbox so that it scales automatically, irrespective of width and height.

  5. For each element in your ItemsControl list create a view model containing X1/Y1/X2/Y2, then use a DataTemplate to render those items using those values to draw a vertical line.


So basically your main view model should look something like this (which by way of demonstration is generating random data points):



public class MainViewModel : ObservableObject
{
private IEnumerable<DataPointViewModel> _DataPoints;
public IEnumerable<DataPointViewModel> DataPoints
{
get { return this._DataPoints; }
set { Set(() => this.DataPoints, ref this._DataPoints, value); }
}

public int ChartWidth { get; } = 1000;
public int ChartHeight { get; } = 1000;

public MainViewModel()
{
var rng = new Random();
this.DataPoints = Enumerable.Range(0, this.ChartWidth)
.Select(x => new DataPointViewModel {X1 = x, Y1 = this.ChartHeight-1, X2 = x, Y2 = this.ChartHeight - 1 - rng.Next(this.ChartHeight) });
}
}


The view model for the items in your collection need to provide the points for the line that is used to render them:



public class DataPointViewModel : ObservableObject
{
private double _X1;
public double X1
{
get { return this._X1; }
set { Set(() => this.X1, ref this._X1, value); }
}

private double _Y1;
public double Y1
{
get { return this._Y1; }
set { Set(() => this.Y1, ref this._Y1, value); }
}

private double _X2;
public double X2
{
get { return this._X2; }
set { Set(() => this.X2, ref this._X2, value); }
}

private double _Y2;
public double Y2
{
get { return this._Y2; }
set { Set(() => this.Y2, ref this._Y2, value); }
}
}


And then your XAML simply uses these to render a line for each data point on a Canvas control:



<Viewbox>
<ItemsControl ItemsSource="{Binding DataPoints}" Width="{Binding ChartWidth}" Height="{Binding ChartHeight}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Line Stroke="Blue" StrokeThickness="1" X1="{Binding X1}" Y1="{Binding Y1}" X2="{Binding X2}" Y2="{Binding Y2}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Viewbox>


This will all in turn generate the following output:



enter image description here







share|improve this answer












share|improve this answer



share|improve this answer










answered 19 hours ago









Mark Feldman

8,04611638




8,04611638












  • I must mention that I have huge collection of 'DataPoints' so in your solution I need to update DataPoints property constantly Have you compared the performance of constant updating of DataPoints property to the performance of simple Canvas redrawing? I want to keep update rate of the chart around 60fps when user scrolls it. I think that ItemsControl uses the same Add method on Canvas. Am I wrong? I wanted to run your example locally to measure it by myself but I can't find your implementation of ObservableObject anywhere in the internet.
    – Dobby007
    18 hours ago










  • Ah, that's a pretty important detail. In this case I probably wouldn't use WPF, high performance was never one of its primary design features.
    – Mark Feldman
    8 hours ago










  • ObservableObject is part of MVVM Light, you could use ViewModelBase instead or indeed anything else that support INPC. But yeah, if you need real-time high performance then forget data-binding, you're probably going to have to resort to DirectX or something.
    – Mark Feldman
    8 hours ago




















  • I must mention that I have huge collection of 'DataPoints' so in your solution I need to update DataPoints property constantly Have you compared the performance of constant updating of DataPoints property to the performance of simple Canvas redrawing? I want to keep update rate of the chart around 60fps when user scrolls it. I think that ItemsControl uses the same Add method on Canvas. Am I wrong? I wanted to run your example locally to measure it by myself but I can't find your implementation of ObservableObject anywhere in the internet.
    – Dobby007
    18 hours ago










  • Ah, that's a pretty important detail. In this case I probably wouldn't use WPF, high performance was never one of its primary design features.
    – Mark Feldman
    8 hours ago










  • ObservableObject is part of MVVM Light, you could use ViewModelBase instead or indeed anything else that support INPC. But yeah, if you need real-time high performance then forget data-binding, you're probably going to have to resort to DirectX or something.
    – Mark Feldman
    8 hours ago


















I must mention that I have huge collection of 'DataPoints' so in your solution I need to update DataPoints property constantly Have you compared the performance of constant updating of DataPoints property to the performance of simple Canvas redrawing? I want to keep update rate of the chart around 60fps when user scrolls it. I think that ItemsControl uses the same Add method on Canvas. Am I wrong? I wanted to run your example locally to measure it by myself but I can't find your implementation of ObservableObject anywhere in the internet.
– Dobby007
18 hours ago




I must mention that I have huge collection of 'DataPoints' so in your solution I need to update DataPoints property constantly Have you compared the performance of constant updating of DataPoints property to the performance of simple Canvas redrawing? I want to keep update rate of the chart around 60fps when user scrolls it. I think that ItemsControl uses the same Add method on Canvas. Am I wrong? I wanted to run your example locally to measure it by myself but I can't find your implementation of ObservableObject anywhere in the internet.
– Dobby007
18 hours ago












Ah, that's a pretty important detail. In this case I probably wouldn't use WPF, high performance was never one of its primary design features.
– Mark Feldman
8 hours ago




Ah, that's a pretty important detail. In this case I probably wouldn't use WPF, high performance was never one of its primary design features.
– Mark Feldman
8 hours ago












ObservableObject is part of MVVM Light, you could use ViewModelBase instead or indeed anything else that support INPC. But yeah, if you need real-time high performance then forget data-binding, you're probably going to have to resort to DirectX or something.
– Mark Feldman
8 hours ago






ObservableObject is part of MVVM Light, you could use ViewModelBase instead or indeed anything else that support INPC. But yeah, if you need real-time high performance then forget data-binding, you're probably going to have to resort to DirectX or something.
– Mark Feldman
8 hours ago




















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53942844%2fwhats-the-best-way-to-draw-chart-with-discrete-values-on-canvas%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Monofisismo

Angular Downloading a file using contenturl with Basic Authentication

Olmecas