hi ,
i am newer to xamdatachart so i want sample code for developing for crosshair for interpolated data in xamdatachart ,
if anybodies having idea about xamdatachart plz give me some sample
whether crosshair is possible to do in xamdatachart if possible means give me some example ,if not means how can i achieve crosshair
in chart ,plz anybodies give me reply it's very urgent for me
thanks in advance
thanks a lot Graham, it's working once again thank you so much...
--Madhusudan
Make sure you didn't miss merging any changes into your project, there were a lot of updates. I've attached my working project so that you can compare it to your project.
-Graham
hi Graham,
your code is Running without any error but i didn't get any values of intersect vertical and horizontal crosshair for your reference i attached my screenshot
Hi, I didn't share with you the code that does all the intersections because it isn't useful graphically. But in case you want to use the list of intersections in a listbox or something, here it is:
Tooltip template:
<DataTemplate x:Key="tooltipTemplate"> <Border BorderBrush="Gray" BorderThickness="1" CornerRadius="5" Background="White" IsHitTestVisible="False" Padding="5"> <!--<ItemsControl ItemsSource="{Binding}"> <ItemsControl.ItemTemplate> <DataTemplate>--> <StackPanel Orientation="Horizontal"> <ContentPresenter Content="{Binding}" ContentTemplate="{Binding Series.LegendItemBadgeTemplate}" /> <TextBlock Text="Series: " /> <TextBlock Text="{Binding Series.Title}" /> <TextBlock Text=" " /> <TextBlock Text="Value: " /> <TextBlock Text="{Binding Value}" /> </StackPanel> <!--</DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl>--> </Border> </DataTemplate>
Control:
<UserControl x:Class="SilverlightApplication86.XamDataChartHostControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:igChart="clr-namespace:Infragistics.Controls.Charts;assembly=InfragisticsSL4.Controls.Charts.XamDataChart.v10.2" xmlns:igCtrl="clr-namespace:Infragistics.Controls;assembly=InfragisticsSL4.DataVisualization.v10.2" xmlns:local="clr-namespace:SilverlightApplication86" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400"> <UserControl.Resources> <LinearGradientBrush x:Key="rscGradientBackground" StartPoint="0.0, 0.0" EndPoint="1.0, 1.0"> <GradientStop Color="#FFFFFFFF" Offset="0" /> <GradientStop Color="#c0c2c8" Offset="0.4" /> <GradientStop Color="#e0e2e8" Offset="1" /> </LinearGradientBrush> <Style x:Key="rscXamDataChartStyle" TargetType="igChart:XamDataChart"> <Setter Property="PlotAreaBackground" Value="Transparent" /> </Style> <!--<Style x:Key="LegendStyle" TargetType="{x:Type igChart:Legend}"> <Setter Property="Background"> <Setter.Value> <LinearGradientBrush EndPoint="0,1" StartPoint="0,0"> <GradientStop Color="White" Offset="0" /> <GradientStop Color="White" Offset="0.5" /> <GradientStop Color="White" Offset="0.5" /> <GradientStop Color="#FFE8E8EF" Offset="1" /> </LinearGradientBrush> </Setter.Value> </Setter> <Setter Property="BorderBrush" Value="{StaticResource rscGradientBorder}"/> <Setter Property="BorderThickness" Value="0.75" /> <Setter Property="Orientation" Value="Vertical" /> <Setter Property="Padding" Value="4" /> <Setter Property="Margin" Value="2" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type igChart:Legend}"> <Grid Margin="{TemplateBinding Margin}"> <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="3" Background="Transparent" CornerRadius="4"> <Grid Margin="{TemplateBinding Padding}"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <ContentPresenter Content="{TemplateBinding Content}" Margin="0" Grid.Row="1" /> <ScrollViewer BorderThickness="0" HorizontalScrollBarVisibility="Auto" Grid.Row="2" VerticalScrollBarVisibility="Auto" Margin="3,0,0,0"> <ContentPresenter x:Name="ContentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" Grid.Row="1" /> </ScrollViewer> </Grid> </Border> <Border BorderBrush="Transparent" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="4" IsHitTestVisible="False"> <Border.Background> <LinearGradientBrush EndPoint="0,1" Opacity="0" StartPoint="0,0"> <GradientStop Color="Transparent" Offset="0" /> <GradientStop Color="#10FFFFFF" Offset="0.499" /> <GradientStop Color="Transparent" Offset="0.501" /> </LinearGradientBrush> </Border.Background> </Border> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style>--> <LinearGradientBrush x:Key="rscGradientBorder" StartPoint="0.0, 0.0" EndPoint="0.0, 1.0"> <GradientStop Color="#FFFFFFFF" Offset="0" /> <GradientStop Color="#c0c2c8" Offset="0.75" /> <GradientStop Color="#e0e2e8" Offset="1" /> </LinearGradientBrush> </UserControl.Resources> <Border CornerRadius="5" Margin="5" Background="{StaticResource rscGradientBackground}"> <igChart:XamDataChart Grid.Row="1" Name="wpfWebDataChart1" Style="{StaticResource rscXamDataChartStyle}" Legend="{Binding ElementName=Legend}" CrosshairVisibility="Visible" > <!--<igChart:Legend igCtrl:XamDock.Edge="OutsideRight" x:Name="Legend" Style="{DynamicResource LegendStyle}" igCtrl:XamDock.VerticalAlignment="Center" Content="Prices" />--> <local:ChartBehaviors.CursorTooltip> <local:CursorTooltipBehavior TooltipTemplate="{StaticResource tooltipTemplate}" > <local:CursorTooltipBehavior.IntersectionFinder> <local:IntersectionFinder /> </local:CursorTooltipBehavior.IntersectionFinder> </local:CursorTooltipBehavior> </local:ChartBehaviors.CursorTooltip> <igChart:XamDataChart.Axes> <igChart:CategoryXAxis x:Name="XAxis" VerticalAlignment="Top" ItemsSource="{Binding}" /> <igChart:NumericYAxis x:Name="YAxis" /> </igChart:XamDataChart.Axes> <igChart:XamDataChart.Series> <igChart:LineSeries Title="High" Legend="{Binding ElementName=Legend}" XAxis="{Binding ElementName=XAxis}" YAxis="{Binding ElementName=YAxis}" MarkerType="None" ItemsSource="{Binding}" ValueMemberPath="Column2" ToolTip="{}{Series.Title} {Item.Column0:D}: {Item.Column2:C}" /> <igChart:LineSeries Title="Low" XAxis="{Binding ElementName=XAxis}" YAxis="{Binding ElementName=YAxis}" Legend="{Binding ElementName=Legend}" ItemsSource="{Binding}" ValueMemberPath="Column3" ToolTip="{}{Series.Title} {Item.Column0:D}: {Item.Column3:C}" /> <igChart:LineSeries Title="Close" Legend="{Binding ElementName=Legend}" XAxis="{Binding ElementName=XAxis}" YAxis="{Binding ElementName=YAxis}" ItemsSource="{Binding}" ValueMemberPath="Column4" ToolTip="{}{Series.Title} {Item.Column0:D}: {Item.Column4:C}" /> </igChart:XamDataChart.Series> </igChart:XamDataChart> </Border> </UserControl>
Control code behind:
public partial class XamDataChartHostControl : UserControl { private CursorTooltipBehavior curt; public XamDataChartHostControl() { InitializeComponent(); } public XamDataChart XamDataChart { get { return wpfWebDataChart1; } } private void wpfWebDataChart1_SeriesCursorMouseMove(object sender, ChartCursorEventArgs e) { //CursorTooltipBehavior temp = new CursorTooltipBehavior(); //temp.Chart_SeriesCursorMouseMove(sender, e); //if (e.Series != null && e.Item != null) //{ // curt.Chart_SeriesCursorMouseMove(sender , e ); //} } } public class ChartBehaviors : DependencyObject { public static readonly DependencyProperty CursorTooltipProperty = DependencyProperty.RegisterAttached("CursorTooltip", typeof(CursorTooltipBehavior), typeof(ChartBehaviors), new PropertyMetadata(null, (o, e) => CursorTooltipChanged(o as XamDataChart, e.OldValue as CursorTooltipBehavior, e.NewValue as CursorTooltipBehavior))); public static CursorTooltipBehavior GetCursorTooltip(DependencyObject target) { return target.GetValue(CursorTooltipProperty) as CursorTooltipBehavior; } public static void SetCursorTooltip(DependencyObject target, CursorTooltipBehavior behavior) { target.SetValue(CursorTooltipProperty, behavior); } private static void CursorTooltipChanged(XamDataChart chart, CursorTooltipBehavior oldValue, CursorTooltipBehavior newValue) { if (chart == null) { return; } if (oldValue != null) { oldValue.OnDetach(chart); } if (newValue != null) { newValue.OnAttach(chart); } } } public class SeriesItemInfo : INotifyPropertyChanged { private Series _series; public Series Series { get { return _series; } set { _series = value; if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs("Series")); PropertyChanged(this, new PropertyChangedEventArgs("Value")); } } } private object _item; public object Item { get { return _item; } set { _item = value; if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs("Item")); PropertyChanged(this, new PropertyChangedEventArgs("Value")); } } } private Point _position; public Point Position { get { return _position; } set { _position = value; if (PropertyChanged != null) { PropertyChanged( this, new PropertyChangedEventArgs("Position")); } } } private double _value; private FastReflectionHelper _helper = new FastReflectionHelper(); public double Value { get { if (Series == null || Item == null) { return 0.0; } if (Series is AnchoredCategorySeries) { _helper.PropertyName = ((AnchoredCategorySeries)Series) .ValueMemberPath; return Convert.ToDouble(_helper.GetPropertyValue(Item)); } return 0.0; } } public event PropertyChangedEventHandler PropertyChanged; } public class SeriesItemInfoCollection : ObservableCollection<SeriesItemInfo> { internal void UpdateSeriesItems(Series series, IList<Tuple<object, Point>> intersectedAxisItems) { bool found = false; var old = (from curr in this where curr.Series == series select curr).ToList(); foreach (var item in old) { Remove(item); } foreach (var item in intersectedAxisItems) { Add(new SeriesItemInfo() { Series = series, Item = item.Item1, Position = item.Item2 }); } } } public class PopupCollection { private XamDataChart _owner = null; private List<Popup> _popups = new List<Popup>(); public PopupCollection(XamDataChart owner) { _owner = owner; } public void RefreshPopups( IList<SeriesItemInfo> infos, DataTemplate tooltipTemplate, Rect viewportRect) { int index = 0; foreach (var popup in _popups) { if (index >= infos.Count) { break; } ContentControl control = popup.Child as ContentControl; control.ContentTemplate = tooltipTemplate; control.Content = infos[index]; UpdatePopupPosition(popup, infos[index], viewportRect); popup.IsOpen = true; index++; } for (int i = index; i < infos.Count; i++) { Popup popup = new Popup(); popup.Child = new ContentControl(); ContentControl control = popup.Child as ContentControl; control.ContentTemplate = tooltipTemplate; control.Content = infos[i]; UpdatePopupPosition(popup, infos[i], viewportRect); popup.IsOpen = true; Panel container; if (_owner.Parent != null && _owner.Parent is Panel) { container = _owner.Parent as Panel; container.Children.Add(popup); } _popups.Add(popup); index++; } for (int i = index; i < _popups.Count; i++) { _popups[i].IsOpen = false; } } private void UpdatePopupPosition( Popup popup, SeriesItemInfo info, Rect viewportRect) { double xPosition = ((AnchoredCategorySeries)info.Series).XAxis .GetScaledValue( info.Position.X, info.Series.Chart.WindowRect, viewportRect); double yPosition = ((AnchoredCategorySeries)info.Series).YAxis .GetScaledValue( info.Position.Y, info.Series.Chart.WindowRect, viewportRect); popup.HorizontalOffset = xPosition; popup.VerticalOffset = yPosition; } } public class CursorTooltipBehavior { private bool _isOverChart = false; private PopupCollection _popups = null; private ContentControl _content = new ContentControl(); private Panel _container; private XamDataChart _owner = null; private DataTemplate _tooltipTemplate; private SeriesItemInfoCollection _items = new SeriesItemInfoCollection(); public DataTemplate TooltipTemplate { get { return _tooltipTemplate; } set { _tooltipTemplate = value; _content.ContentTemplate = _tooltipTemplate; } } //protected bool IsOverChart //{ // get { return _isOverChart; } // set // { // bool last = _isOverChart; // _isOverChart = value; // if (_isOverChart && !last) // { // ShowPopup(); // } // if (!_isOverChart && last) // { // HidePopup(); // } // } //} public void OnAttach(XamDataChart chart) { if (_owner != null) { OnDetach(_owner); } _owner = chart; chart.MouseLeave += Chart_MouseLeave; chart.MouseMove += Chart_MouseMove; //chart.SeriesCursorMouseMove += Chart_SeriesCursorMouseMove; chart.PropertyUpdated += Chart_PropertyUpdated; _popups = new PopupCollection(_owner); } void Chart_PropertyUpdated(object sender, PropertyUpdatedEventArgs e) { if (e.PropertyName == "CrosshairPoint") { if (e.NewValue != null && e.NewValue is Point && _owner != null) { //get the relevant axes. CategoryXAxis x = _owner.Axes.First((a) => a is CategoryXAxis) as CategoryXAxis; NumericYAxis y = _owner.Axes.First((a) => a is NumericYAxis) as NumericYAxis; //determine the series viewport. Rect viewportRect = GetViewportRect( _owner.Series[0], x, y); Point p = (Point)e.NewValue; double left; double right; double top; double bottom; GetInViewAxisBounds(x, y, viewportRect, out left, out right, out top, out bottom); //get crosshair window values. double windowX = (p.X - _owner.WindowRect.Left) / _owner.WindowRect.Width; double windowY = (p.Y - _owner.WindowRect.Top) / _owner.WindowRect.Height; //interpolate axis values. double xAxisValue = left + (windowX * (right - left)); double yAxisValue = top + (windowY * (bottom - top)); if (!double.IsNaN(xAxisValue) && !double.IsNaN(yAxisValue) && IntersectionFinder != null) { foreach (var series in _owner.Series) { IList<Tuple<object, Point>> intersectedAxisItems = IntersectionFinder.GetIntersectedItemAxisItems( series, new Point(xAxisValue, yAxisValue)); _items.UpdateSeriesItems(series, intersectedAxisItems); } } } } } public IIntersectionFinder IntersectionFinder { get; set; } private void GetInViewAxisBounds( CategoryXAxis x, NumericYAxis y, Rect viewportRect, out double left, out double right, out double top, out double bottom) { left = x.GetUnscaledValue( viewportRect.Left, _owner.WindowRect, viewportRect); right = x.GetUnscaledValue( viewportRect.Right, _owner.WindowRect, viewportRect); top = y.GetUnscaledValue( viewportRect.Top, _owner.WindowRect, viewportRect); bottom = y.GetUnscaledValue( viewportRect.Bottom, _owner.WindowRect, viewportRect); } private Rect GetViewportRect( Series target, CategoryXAxis x, NumericYAxis y) { double top = 0; double left = 0; double bottom = y.ActualHeight; double right = x.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; } chart.MouseLeave -= Chart_MouseLeave; chart.MouseMove -= Chart_MouseMove; //chart.SeriesCursorMouseMove -= Chart_SeriesCursorMouseMove; chart.PropertyUpdated -= Chart_PropertyUpdated; //IsOverChart = false; _items.Clear(); _owner = null; } void Chart_MouseMove(object sender, MouseEventArgs e) { CategoryXAxis x = _owner.Axes.First((a) => a is CategoryXAxis) as CategoryXAxis; NumericYAxis y = _owner.Axes.First((a) => a is NumericYAxis) as NumericYAxis; //determine the series viewport. Rect viewportRect = GetViewportRect( _owner.Series[0], x, y); _popups.RefreshPopups(_items, _tooltipTemplate, viewportRect); //IsOverChart = true; } //public void Chart_SeriesCursorMouseMove(object sender, ChartCursorEventArgs e) //{ // if (e.Series != null && e.Item != null) // { // _items.UpdateSeriesItem(e.Series, e.Item); // } //} public void Chart_MouseLeave(object sender, MouseEventArgs e) { //IsOverChart = false; } } public interface IIntersectionFinder { IList<Tuple<object, Point>> GetIntersectedItemAxisItems( Series series, Point crosshairAxisPosition); }
Test Data:
public class TestData : ObservableCollection<TestDataItem> { private static Random _rand = new Random(); public TestData() { double curr = 10.0; for (int i = 0; i < 100; i++) { if (_rand.NextDouble() < .5) { curr += _rand.NextDouble() * 3.0; } else { curr -= _rand.NextDouble() * 3.0; } Add(new TestDataItem() { Column0 = i, Column1 = curr + _rand.NextDouble() * 3.0, Column2 = curr + _rand.NextDouble() * 3.0, Column3 = curr - _rand.NextDouble() * 3.0, Column4 = curr - _rand.NextDouble() * 3.0 }); } } } public class TestDataItem { public double Column0 { get; set; } public double Column1 { get; set; } public double Column2 { get; set; } public double Column3 { get; set; } public double Column4 { get; set; } } public class IntersectionFinder : IIntersectionFinder { FastReflectionHelper _helper = new FastReflectionHelper(); public IList<Tuple<object, System.Windows.Point>> GetIntersectedItemAxisItems( Series series, System.Windows.Point crosshairAxisPosition ) { var intersections = new List<Tuple<object, Point>>(); int index = 0; _helper.PropertyName = ((AnchoredCategorySeries)series).ValueMemberPath; double prevX = double.NaN; double prevY = double.NaN; foreach (var item in series.ItemsSource.OfType<TestDataItem>()) { double xVal = index; double yVal = Convert.ToDouble(_helper.GetPropertyValue(item)); if (!double.IsNaN(xVal) && !double.IsNaN(yVal)) { if ((prevY < crosshairAxisPosition.Y && yVal >= crosshairAxisPosition.Y) || (prevY > crosshairAxisPosition.Y && yVal <= crosshairAxisPosition.Y)) { intersections.Add(new Tuple<object,Point>( item, new Point(xVal,yVal))); } } index++; prevX = xVal; prevY = yVal; } return intersections; } }
Hope that helps.
i added the sample code through which one you gave me the link , but i didn't get the all intersect values of Horizontal crosshair like which one you attached one screenshot in my thread
here i attached my code and xaml code plz see this , i think i did some mistake ,where i did i unable to findout plz help me this
4705.xaml.txt
6378.Code.txt