Drawing constant lines

Answered (Not Verified) This post has 0 verified answers | 7 Replies | 3 Followers Thread's RSS feed.

intesis
Points 280
Replied On: Fri, Oct 22 2010 5:03 AM Reply

Hi,

Is the any way to draw any constant line in XamDataChart?

I'm interested on draw a line for max value (and min value) from a serie.

Thanks in advanced

  • Post Points: 20

All Replies

Answered (Not Verified) Replied On: Fri, Oct 22 2010 9:09 AM Reply

Hi,

You could probably adapt this sample: http://community.infragistics.com/forums/p/45157/246174.aspx#246174

to display such a line instead of strips.

You could also just create a line series or scatter line series based on your calculation of the minimum and maximum.

You may also want to look at the custom indicator series, for drawing horizontal lines.

-Graham

  • Post Points: 20
intesis
Points 280
Replied On: Fri, Oct 22 2010 10:53 AM Reply

Hi Graham,

can you post any example for custom indicator? seems the best approach.

Thanks

  • Post Points: 20
Answered (Not Verified) Replied On: Thu, Oct 28 2010 11:29 AM Reply

Here's an example of how to approach this using custom indicators:

<UserControl.Resources>
        <local:TestData x:Key="data" />
    </UserControl.Resources>
    
    <Grid x:Name="LayoutRoot" Background="White">
        <igChart:XamDataChart x:Name="theChart">
            <igChart:XamDataChart.Axes>
                <igChart:CategoryXAxis x:Name="xAxis" 
                                       ItemsSource="{StaticResource data}" 
                                       Label="{}{Label}" />
                <igChart:NumericYAxis x:Name="yAxis" MinimumValue="-100" MaximumValue="100" />
            </igChart:XamDataChart.Axes>
            
            <igChart:XamDataChart.Series>
                <igChart:LineSeries x:Name="line"
                                    ItemsSource="{StaticResource data}"
                                    XAxis="{Binding ElementName=xAxis}"
                                    YAxis="{Binding ElementName=yAxis}"
                                    ValueMemberPath="Value"
                                    />
                
                <igChart:CustomIndicator x:Name="min" 
                                         Indicator="CustomIndicator_Indicator"
                                         BasedOnColumns="CustomIndicator_BasedOnColumns"
                                         ItemsSource="{StaticResource data}"
                                         XAxis="{Binding ElementName=xAxis}"
                                         YAxis="{Binding ElementName=yAxis}"
                                         OpenMemberPath="Value" />
                <igChart:CustomIndicator x:Name="max" 
                                         Indicator="max_Indicator"
                                         BasedOnColumns="CustomIndicator_BasedOnColumns"
                                         ItemsSource="{StaticResource data}"
                                         XAxis="{Binding ElementName=xAxis}"
                                         YAxis="{Binding ElementName=yAxis}"
                                         OpenMemberPath="Value" />
            </igChart:XamDataChart.Series>
        </igChart:XamDataChart>
    </Grid>

With code behind:

public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
        }

        private void CustomIndicator_Indicator(object sender, Infragistics.Controls.Charts.FinancialEventArgs e)
        {
            double min = e.DataSource.OpenColumn.Min();
            for (int i = 0; i < e.DataSource.IndicatorColumn.Count; i++)
            {
                e.DataSource.IndicatorColumn[i] = min;
            }
        }

        private void CustomIndicator_BasedOnColumns(object sender, Infragistics.Controls.Charts.FinancialEventArgs e)
        {
            e.BasedOn = new List<string>() { "OpenColumn" };
        }

        private void max_Indicator(object sender, Infragistics.Controls.Charts.FinancialEventArgs e)
        {
            double max = e.DataSource.OpenColumn.Max();
            for (int i = 0; i < e.DataSource.IndicatorColumn.Count; i++)
            {
                e.DataSource.IndicatorColumn[i] = max;
            }
        }
    }

    public  class TestDataItem
    {
        public string Label { get; set; }
        public double Value { get; set; }
    }

    public class TestData
        : ObservableCollection<TestDataItem>
    {
        private static Random _rand = new Random();
        public TestData()
        {
            double curr = 10;
            for (int i = 0; i < 400; i++)
            {
                if (_rand.NextDouble() > .5)
                {
                    curr += _rand.NextDouble() * 3.0;
                }
                else
                {
                    curr -= _rand.NextDouble() * 3.0;
                }

                if (curr < -90)
                {
                    curr = -90;
                }
                if (curr > 90)
                {
                    curr = 90;
                }

                Add(new TestDataItem()
                {
                    Label = i.ToString(),
                    Value = curr
                });
            }
        }
    }

-Graham

  • Post Points: 20
intesis
Points 280
Replied On: Fri, Oct 29 2010 10:10 AM Reply

Thanks a lot, it works fine

  • Post Points: 20
jeromerg25
Points 85
Replied On: Fri, Jan 7 2011 5:45 AM Reply

Hi Graham,

I have the same question with vertical lines: how is it possible to draw vertical lines at specific places in the chart. The previous solution is very good for horizontal lines, but doesn't work for vertical lines.

Need help!

Thank you in advance,

JRG

  • Post Points: 20
Answered (Not Verified) Replied On: Thu, Feb 3 2011 10:10 AM Reply

I made a couple changes to an existing sample of mine to show you one way that you can accomplish this. If you are dealing with a scatter chart and want to draw a vertical line, you can just add an additional scatterline series that draws a line from the minimum to the maximum of your other series y values.

Here is the Xaml:

<Window.Resources>
        <local:TestData x:Key="vm" />
    </Window.Resources>
    <Grid x:Name="LayoutRoot" Background="White">
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <ig:XamDataChart x:Name="theChart" VerticalZoomable="True" HorizontalZoomable="True" >
            <local:ChartBehaviors.ChartStrips>
                <local:ChartStripsBehavior>
                    <local:ChartStripsBehavior.StripTemplate>
                        <DataTemplate>
                            <Border Background="{Binding Fill}"  
                                       Opacity=".4"  
                                       Width="{Binding Width}"  
                                       Height="{Binding Height}"  
                                         >
                                <TextBlock  
                                           FontSize="20"  
                                           HorizontalAlignment="Center"  
                                           VerticalAlignment="Center"  
                                           Text="{Binding Label}"  
                                           RenderTransformOrigin=".5,.5"  
                                           >  
                                           <TextBlock.RenderTransform>  
                                               <RotateTransform Angle="90" />  
                                           </TextBlock.RenderTransform>
                                </TextBlock>
                            </Border>
                        </DataTemplate>
                    </local:ChartStripsBehavior.StripTemplate>
                    <local:ChartStripsBehavior.Strips>
                        <!-- create a strip between indexes 2 and 3 on the category axis -->
                        <local:StripInfo    
                           UseDates="False"  
                           StartX="2"
                           EndX="2"
                           Fill="Red"  
                           Label="Strip1"/>

                        <local:StripInfo  
                           UseDates="False"  
                            StartX="4"
                            EndX="4"
                           Fill="Blue"  
                           Label="Strip2" />
                    </local:ChartStripsBehavior.Strips>
                </local:ChartStripsBehavior>
            </local:ChartBehaviors.ChartStrips>

            <ig:XamDataChart.Axes>
                <ig:CategoryXAxis x:Name="xAxis"    
                                         ItemsSource="{StaticResource vm}"    
                                         Label="{}{Label}" />
                <ig:NumericYAxis x:Name="yAxis" />
            </ig:XamDataChart.Axes>
            <ig:XamDataChart.Series>
                <ig:LineSeries x:Name="line"  
                              XAxis="{Binding ElementName=xAxis}"  
                              YAxis="{Binding ElementName=yAxis}"  
                              ValueMemberPath="Value"  
                              ItemsSource="{StaticResource vm}"/>
            </ig:XamDataChart.Series>
        </ig:XamDataChart>

        <Button Grid.Row="1" x:Name="push" Content="push" Click="push_Click" />
    </Grid>

And the code behind:

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void push_Click(object sender, RoutedEventArgs e)
        {
            StripInfo si = new StripInfo();
            si.StartX = 1;
            si.EndX = 2;
            si.Fill = new SolidColorBrush(Colors.Green);

            ChartBehaviors.GetChartStrips(theChart).Strips.Add(si);
        }
    }

    public class TestData
        : ObservableCollection<TestDataItem>
    {
        public TestData()
        {
            Add(new TestDataItem() { Label = "A", Value = 1 });
            Add(new TestDataItem() { Label = "B", Value = 2 });
            Add(new TestDataItem() { Label = "C", Value = 3 });
            Add(new TestDataItem() { Label = "D", Value = 4 });
            Add(new TestDataItem() { Label = "E", Value = 5 });
            Add(new TestDataItem() { Label = "F", Value = 6 });
            Add(new TestDataItem() { Label = "G", Value = 7 });
        }
    }

    public class TestDataItem
    {
        public string Label { get; set; }
        public double Value { get; set; }
    }

    public class ChartBehaviors
        : DependencyObject
    {
        public static readonly DependencyProperty ChartStripsProperty =
            DependencyProperty.RegisterAttached("ChartStrips",
            typeof(ChartStripsBehavior), typeof(ChartBehaviors),
            new PropertyMetadata(null,
                (o, e) => CursorTooltipChanged(
                    o as XamDataChart,
                    e.OldValue as ChartStripsBehavior,
                    e.NewValue as ChartStripsBehavior)));

        public static ChartStripsBehavior GetChartStrips(
            DependencyObject target)
        {
            return target.GetValue(ChartStripsProperty)
                as ChartStripsBehavior;
        }

        public static void SetChartStrips(
            DependencyObject target, ChartStripsBehavior behavior)
        {
            target.SetValue(ChartStripsProperty, behavior);
        }

        private static void CursorTooltipChanged(
            XamDataChart chart,
            ChartStripsBehavior oldValue,
            ChartStripsBehavior newValue)
        {
            if (chart == null)
            {
                return;
            }
            if (oldValue != null)
            {
                oldValue.OnDetach(chart);
            }
            if (newValue != null)
            {
                newValue.OnAttach(chart);
            }
        }

    }

    public class StripInfo
    {
        public StripInfo()
        {
            _id = Guid.NewGuid();
            StartX = double.NaN;
            EndX = double.NaN;
            StartY = double.NaN;
            EndY = double.NaN;
        }

        private StripInfo(Guid id)
        {
            _id = id;
            StartX = double.NaN;
            EndX = double.NaN;
            StartY = double.NaN;
            EndY = double.NaN;
        }

        private Guid _id;
        public Guid Id
        {
            get { return _id; }
            private set { _id = value; }
        }

        public double StartX { get; set; }
        public double EndX { get; set; }
        public DateTime StartDate { get; set; }
        public DateTime EndDate { get; set; }
        public bool UseDates { get; set; }
        public double StartY { get; set; }
        public double EndY { get; set; }
        public string Label { get; set; }

        public double Width
        {
            get { return Math.Max(Math.Abs(EndX - StartX), 1.0); }
        }

        public double Height
        {
            get { return Math.Abs(EndY - StartY); }
        }

        public Brush Fill { get; set; }

        public DataTemplate StripTemplate { get; set; }

        public StripInfo Clone()
        {
            StripInfo newStripInfo = new StripInfo(_id);
            newStripInfo.StartX = StartX;
            newStripInfo.StartY = StartY;
            newStripInfo.EndX = EndX;
            newStripInfo.EndY = EndY;
            newStripInfo.Label = Label;
            newStripInfo.StripTemplate = StripTemplate;
            newStripInfo.Fill = Fill;
            newStripInfo.UseDates = UseDates;
            newStripInfo.StartDate = StartDate;
            newStripInfo.EndDate = EndDate;

            return newStripInfo;
        }
    }

    public class StripInfoCollection
        : ObservableCollection<StripInfo>
    {

    }

    public class ChartStripsBehavior
        : DependencyObject
    {
        public ChartStripsBehavior()
        {
            Strips = new StripInfoCollection();
        }

        public static readonly DependencyProperty StripsProperty =
            DependencyProperty.Register("Strips",
            typeof(StripInfoCollection),
            typeof(ChartStripsBehavior),
            new PropertyMetadata(null,
                (o, e) =>
                    (o as ChartStripsBehavior)
                    .OnStripsChanged(
                    e.OldValue as StripInfoCollection,
                    e.NewValue as StripInfoCollection)));

        public StripInfoCollection Strips
        {
            get { return (StripInfoCollection)GetValue(StripsProperty); }
            set { SetValue(StripsProperty, value); }
        }

        public DataTemplate StripTemplate { get; set; }

        private void OnStripsChanged(
            StripInfoCollection oldValue,
            StripInfoCollection newValue)
        {
            if (oldValue != null)
            {
                oldValue.CollectionChanged -= Strips_CollectionChanged;
            }

            if (newValue != null)
            {
                newValue.CollectionChanged += Strips_CollectionChanged;
            }
            RefreshStrips();
        }

        void Strips_CollectionChanged(
            object sender,
            NotifyCollectionChangedEventArgs e)
        {
            RefreshStrips();
        }

        private XamDataChart _owner = null;

        public void OnAttach(XamDataChart chart)
        {
            if (_owner != null)
            {
                OnDetach(_owner);
            }
            _owner = chart;

            _owner.WindowRectChanged += Owner_WindowRectChanged;
            _owner.SizeChanged += Owner_SizeChanged;
            _owner.Axes.CollectionChanged += Axes_CollectionChanged;
            _owner.Axes.CollectionResetting += Axes_CollectionResetting;

            RefreshStrips();
        }

        void Owner_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            RefreshStrips();
        }

        void Axes_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.OldItems != null)
            {
                foreach (Axis axis in e.OldItems)
                {
                    axis.SizeChanged -= Axis_SizeChanged;
                }
            }
            if (e.NewItems != null)
            {
                foreach (Axis axis in e.NewItems)
                {
                    axis.SizeChanged += Axis_SizeChanged;
                }
            }
            RefreshStrips();
        }

        void Axis_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            RefreshStrips();
        }

        void Axes_CollectionResetting(object sender, EventArgs e)
        {
            foreach (Axis axis in _owner.Axes)
            {
                axis.SizeChanged -= Axis_SizeChanged;
            }
            RefreshStrips();
        }

        void Owner_WindowRectChanged(object sender, Infragistics.RectChangedEventArgs e)
        {
            RefreshStrips();
        }

        private void GetAxes(
            out Axis xAxis,
            out Axis yAxis)
        {
            if (_owner == null)
            {
                xAxis = null;
                yAxis = null;
                return;
            }

            xAxis =
               (from axis in _owner.Axes
                where axis is NumericXAxis ||
                axis is CategoryXAxis ||
                axis is CategoryDateTimeXAxis
                select axis).FirstOrDefault();

            yAxis =
                (from axis in _owner.Axes
                 where axis is NumericYAxis
                 select axis).FirstOrDefault();
        }

        private void ClearExisting(Axis xAxis)
        {
            if (xAxis.RootCanvas == null)
            {
                return;
            }
            var existing =
               from child in xAxis.RootCanvas.Children.OfType<UIElement>()
               where child is ContentControl &&
               (child as ContentControl).Content != null &&
               (child as ContentControl).Content is StripInfo
               select child;
            existing.ToList().ForEach(
                (ele) => xAxis.RootCanvas.Children.Remove(ele));
        }

        private void RefreshStrips()
        {
            Axis xAxis;
            Axis yAxis;
            GetAxes(out xAxis, out yAxis);

            if (xAxis == null || yAxis == null || xAxis.RootCanvas == null)
            {
                return;
            }

            ClearExisting(xAxis);

            Rect viewport = GetViewportRect(xAxis);

            foreach (StripInfo info in Strips)
            {
                StripInfo toAdd = info.Clone();

                if (!toAdd.UseDates)
                {
                    if (double.IsNaN(toAdd.StartX))
                    {
                        toAdd.StartX = viewport.Left;
                    }
                    else
                    {
                        toAdd.StartX =
                            xAxis.GetScaledValue(
                                toAdd.StartX, _owner.WindowRect, viewport);
                    }
                    if (double.IsNaN(toAdd.EndX))
                    {
                        toAdd.EndX = viewport.Right;
                    }
                    else
                    {
                        toAdd.EndX =
                            xAxis.GetScaledValue(
                                toAdd.EndX, _owner.WindowRect, viewport);
                    }
                }
                else
                {
                    toAdd.StartX =
                        xAxis.GetScaledValue(toAdd.StartDate.Ticks,
                        _owner.WindowRect, viewport);
                    toAdd.EndX =
                        xAxis.GetScaledValue(toAdd.EndDate.Ticks,
                        _owner.WindowRect, viewport);
                }


                if (double.IsNaN(toAdd.StartY))
                {
                    toAdd.StartY = viewport.Top;
                }
                else
                {
                    toAdd.StartY =
                        yAxis.GetScaledValue(
                        toAdd.StartY, _owner.WindowRect, viewport);
                }
                if (double.IsNaN(toAdd.EndY))
                {
                    toAdd.EndY = viewport.Bottom;
                }
                else
                {
                    toAdd.EndY =
                        yAxis.GetScaledValue(
                        toAdd.EndY, _owner.WindowRect, viewport);
                }
                if (toAdd.StripTemplate == null)
                {
                    toAdd.StripTemplate = this.StripTemplate;
                }

                if (toAdd.StripTemplate != null &&
                    !double.IsNaN(toAdd.StartY) &&
                    !double.IsInfinity(toAdd.StartY) &&
                    !double.IsNaN(toAdd.StartX) &&
                    !double.IsInfinity(toAdd.StartX))
                {
                    ContentControl stripControl = new ContentControl();
                    stripControl.ContentTemplate = toAdd.StripTemplate;
                    stripControl.Content = toAdd;
                    Canvas.SetLeft(stripControl, toAdd.StartX);
                    Canvas.SetTop(stripControl, toAdd.StartY);

                    xAxis.RootCanvas.Children.Add(stripControl);
                }
            }
        }

        private Rect GetViewportRect(
            Axis axis)
        {
            double top = 0;
            double bottom = axis.ActualHeight;
            double left = 0;
            double right = axis.ActualWidth;

            double width = right - left;
            double height = bottom - top;

            if (width > 0.0 && height > 0.0)
            {
                return new Rect(left, top, width, height);
            }
            return Rect.Empty;
        }

        public void OnDetach(XamDataChart chart)
        {
            if (_owner != chart)
            {
                return;
            }

            _owner.WindowRectChanged -= Owner_WindowRectChanged;
            _owner.SizeChanged -= Owner_SizeChanged;
            _owner.Axes.CollectionChanged -= Axes_CollectionChanged;
            _owner.Axes.CollectionResetting -= Axes_CollectionResetting;

            Axis xAxis;
            Axis yAxis;
            GetAxes(out xAxis, out yAxis);

            if (xAxis == null || yAxis == null)
            {
                return;
            }

            ClearExisting(xAxis);

            _owner = null;
        }
    }


Hope this helps!

You could also probably approximate a vertical line with a step line series or area series, perhaps, that moves to the maximum Y of your other series at the places where you want a line, but I'm not certain you would end up with a straight vertical line.


-Graham

  • Post Points: 20
Alenka1
Points 235
Replied On: Mon, Feb 21 2011 9:46 AM Reply

Hi Graham,

You really helped me with little working example in post Binding ADO and xamDataChart. Could you give me the same little working example for vertical lines, please. The above example is too complicated for me((

  • Post Points: 5
Page 1 of 1 (8 items) | RSS