Jump to content
Software FX Community

kelias

Members
  • Posts

    29
  • Joined

  • Last visited

  • Days Won

    3

Posts posted by kelias

  1. I would like to build a chart with two series. One a bar the other a step. When I try this the chart only shows the step and not the bars. I can display both individually but not together. Here is the code:

    chtMain.Series.Clear();

    chtMain.AxesY.Clear();

    Axis a = new Axis {AutoScale = true, ForceZero = false, Labels = {Decimals = 2}, Title = new Title("value")};

    chtMain.AxesY.Add(a);

    chtMain.AxisX.Labels.Format = AxisFormat.Time;

    chtMain.AxisX.Labels.CustomFormat = "HH:mm";

    chtMain.AxisX.Title = new Title("Time");

    SeriesAttributes series = new SeriesAttributes("Value");

    series.AxisY = a;

    series.Content = "My Value";

    series.BindingPathX = "Date";

    series.Gallery = Gallery.Step;

    series.Volume = 100;

    series.Marker.Visibility = Visibility.Collapsed;

    chtMain.Series.Add(series);

    SeriesAttributes series2 = new SeriesAttributes("Value");

    series2.AxisY = a;

    series2.Content = "My Value2";

    series2.BindingPathX = "Date";

    series2.Gallery = Gallery.Bar;

    series2.Marker.Visibility = Visibility.Collapsed;

    chtMain.Series.Add(series2);

    series.ItemsSource = GetData();

    series2.ItemsSource = GetData();

    -------------

    XAML

    What am I missing?

  2. The XAML:

    
    

    <Window x:Class="ChartfxTest.MainWindow"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:cfx="http://schemas.softwarefx.com/chartfx/wpf/80"

    xmlns:cfxmotifs="http://schemas.softwarefx.com/chartfx/wpf/80/motifs" Title="MainWindow" Height="350" Width="525">

    <Grid>

    <cfx:Chart x:Name="chtMain" Gallery="Line" UseEffects="True" UseVisuals="True" BorderThickness="0" Style="{x:Static cfxmotifs:Basic.Style}" Border="{x:Static cfx:Borders.None}" >

    <cfx:Chart.PlotArea>

    <cfx:PlotAreaAttributes/>

    </cfx:Chart.PlotArea>

    <cfx:Chart.LegendBox>

    <cfx:LegendBox DockPanel.Dock="Bottom"/>

    </cfx:Chart.LegendBox>

    </cfx:Chart>

    </Grid>

    </Window>

    And the code behind

    
    

    using System;

    using System.Collections.Generic;

    using System.Windows;

    using ChartFX.WPF;

    namespace ChartfxTest

    {

    public partial class MainWindow : Window

    {

    public MainWindow()

    {

    InitializeComponent();

    Loaded += MainWindow_Loaded;

    }

    private void MainWindow_Loaded(object sender, RoutedEventArgs e)

    {

    chtMain.Series.Clear();

    chtMain.AxesY.Clear();

    Axis a = new Axis {AutoScale = true, ForceZero = false, Labels = {Decimals = 2}, Title = new Title("MW")};

    chtMain.AxesY.Add(a);

    chtMain.AxisX.Labels.Format = AxisFormat.DateTime;

    chtMain.AxisX.Labels.CustomFormat = "HH:mm";

    chtMain.AxisX.Title = new Title("Time");

    SeriesAttributes series = new SeriesAttributes("Value");

    series.AxisY = a;

    series.Content = "My Value";

    series.BindingPathX = "Date";

    series.Gallery = Gallery.Line;

    chtMain.Series.Add(series);

    List<TimeSeries> data = GetData();

    series.ItemsSource = data;

    }

    private List<TimeSeries> GetData()

    {

    List<TimeSeries> data = new List<TimeSeries>();

    Random rnd = new Random();

    for (int i = 0; i < 50; i++)

    {

    data.Add(new TimeSeries {Date = DateTime.Today.AddHours(i), Value = rnd.Next(0, 100)});

    }

    return data;

    }

    }

    public class TimeSeries

    {

    public DateTime Date { get; set; }

    public int Value { get; set; }

    }

    }

    When I run this it still shows dates in 12 hour format. And when the chart is resized the labels get all squished together.

  3. Your example doesn't even include time. I'm doing all this in code instead of XAML. Here is an example

    
    

    chtMain.AxisX.Labels.Format = AxisFormat.DateTime;

    chtMain.AxisX.Labels.CustomFormat = "HH:mm";

    When I do this the time is shown but it's still in a 12 hour clock, and then it also looses the ability to change depending on the size of the chart. So if I have 1000 data-points, it then puts a label for each data point instead of only those that fit.

  4. Nevermind got it working.

    Heres what I did:

    In the XAML I added two annotations for the horizontal and vertical lines. (note the binding, to span to the size of the container)

    
    

    <cfx:Chart.Extensions>

    <cfxAnnotation:Annotations x:Name="annotations">

    <Line x:Name="lineH" Visibility="Visible" Fill="Black" Stroke="Black" X1="0" X2="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Canvas}},Path=Width}" />

    <Line x:Name="lineV" Visibility="Visible" Fill="Black" Stroke="Black" Y1="0" Y2="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Canvas}},Path=Height}" />

    </cfxAnnotation:Annotations>

    </cfx:Chart.Extensions>

    C# Code

    
    

    private void OnChartMouseMove(object sender, MouseEventArgs e)

    {

    HitTestResults hitTest = chart1.HitTest(e.GetPosition(chart1));

    if (!hitTest.IsInsidePlotArea) return;

    Axis axisX = chart1.AxisX;

    Axis axisY = chart1.AxisY;

    FrameworkElement parent = lineH.Parent as FrameworkElement;

    lineH.Y1 = e.GetPosition(parent).Y;

    lineH.Y2 = e.GetPosition(parent).Y;

    lineV.X1 = e.GetPosition(parent).X;

    lineV.X2 = e.GetPosition(parent).X;

    }

  5. When the user moves the mouse over the chart I would like a crosshair to appear and track with the mouse. (vertical and horizonal line that intersect at the current mouse location) This should only be on the chart portion and not on the legend or titles etc..

    I assume I would use annotation's to accomplish this? Do you have a sample of this anywhere?

    Thanks,

  6. If you use the example above and bind the collection to the chart instead of the series it doesn't seem to resize correctly. When an item is added it refreshes properly but when I remove an item the chart does not scale the x axis correctly reclaiming the space. But it does work if you assign it to each series instead. (Let me know if I'm missing something here.)

    Our charts use the X axis as a time, and the datapoints are not equally spaced.

  7. I have a chart that I want to appear to scroll so it only shows a certain number of data points. I have the chart bound to an ObservableCollection, so when I get an item to add to the collection I remove the first item from the collection. This works fine except with Zoom. When I zoom and data comes in the chart throws a NullReferenceException. (I have the full stacktrace at the bottom)

    Here is some code to reproduce the problem:

    
    

    using System;

    using System.Collections.ObjectModel;

    using System.ComponentModel;

    using System.Windows;

    using ChartFX.WPF;

    namespace ChartTest3

    {

    public partial class Window1 : Window

    {

    private readonly ObservableCollection<MyObject> col = new ObservableCollection<MyObject>();

    public Window1()

    {

    InitializeComponent();

    for (int i = 0; i < 10; i++)

    {

    col.Add(new MyObject {EffectiveDate = DateTime.Now.AddMinutes(i), Value1 = 1000, Value2 = 700});

    }

    myChart.Series.Clear();

    myChart.AxesY.Clear();

    Axis a = new Axis();

    a.AutoScale = true;

    a.ForceZero = false;

    myChart.AxesY.Add(a);

    myChart.AxisX.Labels.Format = AxisFormat.DateTime;

    SeriesAttributes series1 = new SeriesAttributes("Value1");

    series1.BindingPathX = "EffectiveDate";

    series1.Gallery = Gallery.Line;

    series1.AxisY = a;

    myChart.Series.Add(series1);

    series1.ItemsSource = col;

    SeriesAttributes series2 = new SeriesAttributes("Value2");

    series2.BindingPathX = "EffectiveDate";

    series2.Gallery = Gallery.Line;

    series2.AxisY = a;

    myChart.Series.Add(series2);

    series2.ItemsSource = col;

    }

    private void button1_Click(object sender, RoutedEventArgs e)

    {

    col.Add(new MyObject {EffectiveDate = col[col.Count - 1].EffectiveDate.AddMinutes(1), Value1 = 1000, Value2 = 700});

    col.RemoveAt(0);

    }

    private void button2_Click(object sender, RoutedEventArgs e)

    {

    myChart.Zoom.Mode = ZoomMode.Selection;

    }

    }

    public class MyObject : INotifyPropertyChanged

    {

    private DateTime effectiveDate;

    private decimal value1;

    private decimal value2;

    public DateTime EffectiveDate

    {

    get { return effectiveDate; }

    set

    {

    effectiveDate = value;

    if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("EffectiveDate"));

    }

    }

    public decimal Value1

    {

    get { return value1; }

    set

    {

    value1 = value;

    if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("Value1"));

    }

    }

    public decimal Value2

    {

    get { return value2; }

    set

    {

    value2 = value;

    if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("Value2"));

    }

    }

    public event PropertyChangedEventHandler PropertyChanged;

    }

    }

    And the XAML:

    
    

    <Window x:Class="ChartTest3.Window1"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    xmlns:my="clr-namespace:ChartFX.WPF;assembly=ChartFX.WPF"

    xmlns:Motifs="clr-namespace:ChartFX.WPF.Motifs;assembly=ChartFX.WPF"

    Title="Window1" Height="390" Width="675">

    <Grid>

    <my:Chart x:Name="myChart" Gallery="Line" UseEffects="True" UseVisuals="True" Background="White" BorderThickness="0" Style="{x:Static Motifs:Basic.Style}" Palette="{x:Static my:Palettes.Basic}" Margin="0,4,0,79" >

    <my:Chart.Titles>

    <my:Title Content="Test"/>

    </my:Chart.Titles>

    </my:Chart>

    <Button Height="23" HorizontalAlignment="Left" Margin="68,0,0,8" Name="button1" VerticalAlignment="Bottom" Width="75" Click="button1_Click">Button</Button>

    <Button Height="23" HorizontalAlignment="Left" Margin="188,0,0,12" Name="button2" VerticalAlignment="Bottom" Width="75" Click="button2_Click">Button</Button>

    </Grid>

    </Window>

    Click the right button to put the chart into ZoomMode.Selection. Then select a range. Now that the range is selected click the left button to add a point to the ObservableCollection and remove one. Click this a few times and you will get the NullReferenceException.

    Here is the full error I get:

    
    

    System.NullReferenceException was unhandled

    Message="Object reference not set to an instance of an object."

    Source="ChartFX.WPF"

    StackTrace:

    at ChartFX.WPF.SeriesAttributes.ChartFX.WPF.Internal.IDataTarget.ReadData(IEnumerable data, Int32 from, Int32 count, NotifyCollectionChangedAction action, DataBindingHelper bindingHelper)

    at ChartFX.WPF.Internal.DataBindingHelper.a(Object A_0, IEnumerable A_1, Int32 A_2, Int32 A_3, NotifyCollectionChangedAction A_4)

    at ChartFX.WPF.Internal.DataBindingHelper.a(Object A_0, NotifyCollectionChangedEventArgs A_1)

    at System.Collections.Specialized.NotifyCollectionChangedEventHandler.Invoke(Object sender, NotifyCollectionChangedEventArgs e)

    at System.Collections.ObjectModel.ObservableCollection`1.OnCollectionChanged(NotifyCollectionChangedEventArgs e)

    at System.Collections.ObjectModel.ObservableCollection`1.InsertItem(Int32 index, T item)

    at System.Collections.ObjectModel.Collection`1.Add(T item)

    at ChartTest3.Window1.button1_Click(Object sender, RoutedEventArgs e) in C:\dev\ChartTest3\ChartTest3\Window1.xaml.cs:line 49

    at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)

    at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)

    at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)

    at System.Windows.UIElement.RaiseEvent(RoutedEventArgs e)

    at System.Windows.Controls.Primitives.ButtonBase.OnClick()

    at System.Windows.Controls.Button.OnClick()

    at System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonUp(MouseButtonEventArgs e)

    at System.Windows.UIElement.OnMouseLeftButtonUpThunk(Object sender, MouseButtonEventArgs e)

    at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)

    at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)

    at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)

    at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)

    at System.Windows.UIElement.ReRaiseEventAs(DependencyObject sender, RoutedEventArgs args, RoutedEvent newEvent)

    at System.Windows.UIElement.CrackMouseButtonEventAndReRaiseEvent(DependencyObject sender, MouseButtonEventArgs e)

    at System.Windows.UIElement.OnMouseUpThunk(Object sender, MouseButtonEventArgs e)

    at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)

    at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)

    at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)

    at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)

    at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)

    at System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)

    at System.Windows.Input.InputManager.ProcessStagingArea()

    at System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)

    at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)

    at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel)

    at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)

    at System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)

    at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)

    at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)

    at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Boolean isSingleParameter)

    at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler)

    at System.Windows.Threading.Dispatcher.WrappedInvoke(Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler)

    at System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Boolean isSingleParameter)

    at System.Windows.Threading.Dispatcher.Invoke(DispatcherPriority priority, Delegate method, Object arg)

    at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)

    at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)

    at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)

    at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)

    at System.Windows.Threading.Dispatcher.Run()

    at System.Windows.Application.RunDispatcher(Object ignore)

    at System.Windows.Application.RunInternal(Window window)

    at System.Windows.Application.Run(Window window)

    at System.Windows.Application.Run()

    at ChartTest3.App.Main() in C:\dev\ChartTest3\ChartTest3\obj\Debug\App.g.cs:line 0

    at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)

    at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)

    at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()

    at System.Threading.ThreadHelper.ThreadStart_Context(Object state)

    at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)

    at System.Threading.ThreadHelper.ThreadStart()

    InnerException:

    Any ideas what I can do to get around this problem? Preferably I would like the zoom to stay in the current position, so if the user sets the zoom to show the last 10 items I would like it to show the last 10 items always. So if I add an item it would show in the zoom and remove one off the left side.

  8. When I attempt to zoom a chart I'm getting an exception being thrown by ChartFx: ArgumentOutOfRangeException.

    I have a basic chart, and I add a Line series that uses Dates as the X axis. Then I bind to an observablecollection that has the data points.

    The chart displays fine but when I click on button2 to do a zoom I get the error.

    Any ideas why this is happening?

    
    

    private void button2_Click(object sender, RoutedEventArgs e)

    {

    chart1.Zoom.Mode = ZoomMode.Selection;

    }

    private void NormalLineChart()

    {

    chart1.Series.Clear();

    chart1.AxesY.Clear();

    chart1.LegendBox.Visibility = Visibility.Visible;

    Axis a = new Axis();

    a.Min = 0;

    a.Max = 50;

    SeriesAttributes series = new SeriesAttributes("What");

    series.BindingPathX = "When";

    series.Gallery = Gallery.Line;

    series.AxisY = a;

    series.Marker.Visibility = Visibility.Collapsed;

    series.StrokeThickness = 2;

    chart1.Series.Add(series);

    chart1.AxisX.Labels.Format = AxisFormat.Date;

    chart1.ItemsSource = LoadRandomDateTimeData(10, 0, 50, 10);

    }

    private ObservableCollection LoadRandomDateTimeData(int seed, int min, int max, int correlation)

    {

    ObservableCollection dps = new ObservableCollection();

    Random rnd = new Random(seed);

    int last = min;

    for (int i = 0; i < 100; i++)

    {

    int itm = rnd.Next(last - correlation, last + correlation);

    if (itm < min) itm = rnd.Next(min, last + correlation);

    if (itm > max) itm = rnd.Next(last - correlation, max);

    last = itm;

    dps.Add(new DataPoint(itm, DateTime.Today.AddDays(i)));

    }

    return dps;

    }

    public class DataPoint : INotifyPropertyChanged

    {

    private double what;

    private DateTime when;

    public DataPoint()

    {

    }

    public DataPoint(double what, DateTime when)

    {

    What = what;

    When = when;

    }

    public double What

    {

    get { return what; }

    set

    {

    what = value;

    if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("What"));

    }

    }

    public DateTime When

    {

    get { return when; }

    set

    {

    when = value;

    if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("When"));

    }

    }

    public event PropertyChangedEventHandler PropertyChanged;

    }

  9. I'm trying to implement behaviour similiar to google finance where a user moves the mouse over a chart and it tracks on each series and displays the values for each series on the top of the chart.

    I can use the HitTest method of the chart in the MouseMove event to determine when the user is in the Plot Area, but I can't find a nice way to determine what the value of each series should be.

    Is there a simple way to take a Point object and determine what value for each series would match with it? 

     

  10. Any idea why I can't seem to move the magnifier? It doesn't seem to respond at all to the mouse. I've tried left-clicking and dragging, I've right-clicked and tried dragging etc.. but nothing.

  11. <p> 

    Do you have an example of using Annotations in the code behind? I haven't been able to find one. I'm trying this but it's not working.

     </p>

    <pre>

    Rectangle r = new Rectangle();r.Width = 80;

    r.Height = 20;

    r.Fill = new SolidColorBrush(Colors.Blue);

     

    Annotations an = new Annotations();

    an.Children.Add®;

    Annotations.SetAttachX(r, 10);Annotations.SetAttachY(r, 10);

    chart1.Extensions.Add(an);

    </pre>

  12. Just need to call this method:

    
    

    private void NormalLineChart()

    {

    Axis a = new Axis();

    a.Min = 0;

    a.Max = 50;

    chart1.AxesY.Add(a);

    List dps = LoadRandomDateTimeData(10,0,50,10);

    SeriesAttributes series = new SeriesAttributes("What");

    series.BindingPathX = "When";

    series.Gallery = Gallery.Line;

    series.ItemsSource = dps;

    series.AxisY = a;

    series.Marker.Visibility = Visibility.Collapsed;

    series.StrokeThickness = 2;

    chart1.Zoom.Mode = ZoomMode.Magnifier;

    chart1.Series.Add(series);

    chart1.AxisX.Labels.Format = AxisFormat.Date;

    }

    private List LoadRandomDateTimeData(int seed, int min, int max, int correlation)

    {

    List dps = new List();

    Random rnd = new Random(seed);

    int last = min;

    for (int i = 0; i < 100; i++)

    {

    int itm = rnd.Next(last-correlation, last+correlation);

    if (itm

    if (itm > max) itm = rnd.Next(last-correlation, max);

    last = itm;

    dps.Add(new DataPoint(itm, DateTime.Today.AddDays(i)));

    }

    return dps;

    }

    public class DataPoint

    {

    public double What { get; set;}

    public DateTime When { get; set;}

    public DataPoint()

    {}

    public DataPoint(double what, DateTime when)

    {

    What = what;

    When = when;

    }

    }

  13. The users of my charting application have asked for the ability to do basic trend-lines. They need horizontal trend lines. I can add a series to mimic a trend-line but I'm not sure if it's possible to let them move the series through a drag like operation. Any ideas if this is possible?

  14. I have tried to turn on the zoom feature and I can get the magnifier to appear but it doesn't seem to respond to mouse input. I can't drag it or move it around at all. What am I missing?

     I'm doing this: 

    chart1.Zoom.Mode =

    ZoomMode.Magnifier;
×
×
  • Create New...