We have a requirement where we need to change the color of column series based on the underlying value. We have a reference value set to 0 for NumericYAxis which means negative value bars need to displayed with different color. Also some bars need to be painted differently based on estimate val etc.
It would be great if we can override some sort of DataTemplate to drive this req based on the data-triggers
please see:
http://community.infragistics.com/forums/p/48210/256989.aspx#256989
-Graham
Hi Graham,
I have similar requirements and can get by with only a column chart. Has anyone suggested or can you recomend a competitive product that might be able to bind colors to series elements?
Obviously the data is all there (see Tooltip Item values examples). This seems so fundamental.
Bob Hall
Here's a modification of the above sample to show how to map to the original data items and pick the color from there.
<Window.Resources> <local:TestData x:Key="data" /> </Window.Resources> <Grid> <igChart:XamDataChart x:Name="theChart" VerticalZoomable="True" HorizontalZoomable="True"> <igChart:XamDataChart.Resources> <Style TargetType="Rectangle"> <Setter Property="local:StyleBinder.StyleBinderHelper"> <Setter.Value> <local:StyleBinderHelper> <local:StyleBinderHelper.Template> <DataTemplate> <local:RectangleColorChanger XAxis="{Binding OuterContext.Series.XAxis}" Rectangle="{Binding Owner}" ColorPath="Color"/> </DataTemplate> </local:StyleBinderHelper.Template> </local:StyleBinderHelper> </Setter.Value> </Setter> </Style> </igChart:XamDataChart.Resources> <igChart:XamDataChart.Axes> <igChart:NumericYAxis x:Name="yAxis" /> <igChart:CategoryXAxis x:Name="xAxis" ItemsSource="{StaticResource data}" Label="{}{Label}"/> </igChart:XamDataChart.Axes> <igChart:XamDataChart.Series> <igChart:ColumnSeries x:Name="series" ItemsSource="{StaticResource data}" XAxis="{Binding ElementName=xAxis}" YAxis="{Binding ElementName=yAxis}" ValueMemberPath="Value" /> </igChart:XamDataChart.Series> </igChart:XamDataChart> </Grid>
and code behind:
public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } } public class TestData : ObservableCollection<TestDataItem> { public TestData() { Add(new TestDataItem() { Label = "A", Value = 1, Color = new SolidColorBrush(Colors.Red) }); Add(new TestDataItem() { Label = "B", Value = 2, Color = new SolidColorBrush(Colors.Green) }); Add(new TestDataItem() { Label = "C", Value = 3, Color = new SolidColorBrush(Colors.Blue) }); Add(new TestDataItem() { Label = "D", Value = -1, Color = new SolidColorBrush(Colors.Orange) }); Add(new TestDataItem() { Label = "E", Value = -2, Color = new SolidColorBrush(Colors.Olive) }); Add(new TestDataItem() { Label = "F", Value = -1, Color = new SolidColorBrush(Colors.Tan) }); Add(new TestDataItem() { Label = "G", Value = 1, Color = new SolidColorBrush(Colors.Gold) }); Add(new TestDataItem() { Label = "H", Value = 2, Color = new SolidColorBrush(Colors.Firebrick) }); } } public class TestDataItem { public string Label { get; set; } public double Value { get; set; } public Brush Color { get; set; } } public static class StyleBinder { public static readonly DependencyProperty StyleBinderHelperProperty = DependencyProperty.RegisterAttached( "StyleBinderHelper", typeof(StyleBinderHelper), typeof(StyleBinder), new PropertyMetadata(null, (o, e) => StyleBinderHelperChanged(o, e))); private static void StyleBinderHelperChanged( DependencyObject o, DependencyPropertyChangedEventArgs e) { FrameworkElement ele = o as FrameworkElement; if (ele == null) { return; } BindingExpression be = ele.GetBindingExpression ( StyleBinder.StyleBinderContextProperty); if (be == null) { ele.SetBinding(StyleBinderContextProperty, new Binding()); } if (e.NewValue != null) { ((StyleBinderHelper)e.NewValue).PushContent(ele); } } public static void SetStyleBinderHelper( DependencyObject target, StyleBinderHelper value) { target.SetValue(StyleBinderHelperProperty, value); } public static StyleBinderHelper GetStyleBinderHelper( DependencyObject target) { return (StyleBinderHelper)target.GetValue(StyleBinderHelperProperty); } public static readonly DependencyProperty StyleBinderContentProperty = DependencyProperty.RegisterAttached( "StyleBinderContent", typeof(FrameworkElement), typeof(StyleBinder), new PropertyMetadata(null, (o, e) => StyleBinderContentChanged(o, e))); private static void StyleBinderContentChanged( DependencyObject o, DependencyPropertyChangedEventArgs e) { } public static void SetStyleBinderContent( DependencyObject target, FrameworkElement value) { target.SetValue(StyleBinderContentProperty, value); } public static FrameworkElement GetStyleBinderContent( DependencyObject target) { return (FrameworkElement)target.GetValue(StyleBinderContentProperty); } public static readonly DependencyProperty StyleBinderContextProperty = DependencyProperty.RegisterAttached( "StyleBinderContext", typeof(object), typeof(StyleBinder), new PropertyMetadata(null, (o, e) => StyleBinderContextChanged(o, e))); private static void StyleBinderContextChanged( DependencyObject o, DependencyPropertyChangedEventArgs e) { FrameworkElement content = StyleBinder.GetStyleBinderContent(o); if (content != null) { content.DataContext = new HelperContext() { OuterContext = e.NewValue, Owner = o as FrameworkElement }; } } public static void SetStyleBinderContext( DependencyObject target, object value) { target.SetValue(StyleBinderContextProperty, value); } public static object GetStyleBinderContext( DependencyObject target) { return target.GetValue(StyleBinderContextProperty); } } public class StyleBinderHelper : FrameworkElement { internal void PushContent(FrameworkElement ele) { if (Template == null) { return; } FrameworkElement content = Template.LoadContent() as FrameworkElement; if (content == null) { return; } content.DataContext = new HelperContext() { OuterContext = StyleBinder.GetStyleBinderContext(ele), Owner = ele }; StyleBinder.SetStyleBinderContent(ele, content); } public DataTemplate Template { get; set; } } public class HelperContext : INotifyPropertyChanged { private object _outerContext; public object OuterContext { get { return _outerContext; } set { _outerContext = value; RaisePropertyChanged("OuterContext"); } } private FrameworkElement _owner; public FrameworkElement Owner { get { return _owner; } set { _owner = value; RaisePropertyChanged("Owner"); } } public event PropertyChangedEventHandler PropertyChanged; private void RaisePropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } } public class RectangleColorChanger : FrameworkElement { public static readonly DependencyProperty RectangleProperty = DependencyProperty.Register( "Rectangle", typeof(Rectangle), typeof(RectangleColorChanger), new PropertyMetadata(null, (o, e) => (o as RectangleColorChanger) .RectangleChanged(e))); private double _oldMiddle = double.NaN; private void UpdateColor() { if (XAxis == null) { return; } if (Rectangle == null) { return; } Rect viewport = new Rect(0, 0, XAxis.ActualWidth, XAxis.ActualHeight); Rect window = XAxis.Chart.WindowRect; double middle = Rectangle.TransformToVisual(XAxis).Transform(new Point(Rectangle.ActualWidth / 2.0, 0)).X; _oldMiddle = middle; middle = window.Left + window.Width * (middle - viewport.Left) / viewport.Width; double left = XAxis.GetUnscaledValue(viewport.Left, window, viewport); double right = XAxis.GetUnscaledValue(viewport.Right, window, viewport); double windowX = (middle - window.Left) / window.Width; double index = left + (windowX * (right - left)); index -= .5; int indexNumber = (int)Math.Round(index); SetBinding(ColorProperty, new Binding(ColorPath) { Source = XAxis.ItemsSource .OfType<object>() .Skip(indexNumber) .Take(1) .FirstOrDefault() }); } private void UpdateRectangleColor() { if (Rectangle == null) { return; } Rectangle.Fill = Color; Rectangle.LayoutUpdated += new EventHandler(Rectangle_LayoutUpdated); } void Rectangle_LayoutUpdated(object sender, EventArgs e) { if (Rectangle.Parent == null) { Rectangle.LayoutUpdated -= Rectangle_LayoutUpdated; return; } double middle = Rectangle.TransformToVisual(XAxis).Transform(new Point(Rectangle.ActualWidth / 2.0, 0)).X; if (middle != _oldMiddle) { UpdateColor(); } } private void RectangleChanged(DependencyPropertyChangedEventArgs e) { UpdateColor(); } public Rectangle Rectangle { get { return (Rectangle)GetValue(RectangleProperty); } set { SetValue(RectangleProperty, value); } } public static readonly DependencyProperty XAxisProperty = DependencyProperty.Register( "XAxis", typeof(CategoryXAxis), typeof(RectangleColorChanger), new PropertyMetadata(null, (o, e) => (o as RectangleColorChanger) .XAxisChanged(e))); private void XAxisChanged( DependencyPropertyChangedEventArgs e) { UpdateColor(); } public CategoryXAxis XAxis { get { return (CategoryXAxis)GetValue(XAxisProperty); } set { SetValue(XAxisProperty, value); } } public static readonly DependencyProperty ColorProperty = DependencyProperty.Register( "Color", typeof(Brush), typeof(RectangleColorChanger), new PropertyMetadata(null, (o, e) => (o as RectangleColorChanger) .ColorChanged(e))); private void ColorChanged( DependencyPropertyChangedEventArgs e) { UpdateRectangleColor(); } public Brush Color { get { return (Brush)GetValue(ColorProperty); } set { SetValue(ColorProperty, value); } } public static readonly DependencyProperty ColorPathProperty = DependencyProperty.Register( "ColorPath", typeof(string), typeof(RectangleColorChanger), new PropertyMetadata("", (o, e) => (o as RectangleColorChanger) .ColorPathChanged(e))); private void ColorPathChanged( DependencyPropertyChangedEventArgs e) { UpdateColor(); } public string ColorPath { get { return (string)GetValue(ColorPathProperty); } set { SetValue(ColorPathProperty, value); } } }
Hope this helps!-Graham
Hi,
I know this is an old post but its essential for our projects.
I am using InfragisticsSL5.Controls.Charts.XamDataChart.v13.2 and this approach is not working.
Can you please suggest another way to color (in red) the negative values of a column series (only the background of the bars that point down)?
Thank you in advance,
Neo
Unfortunately, due to a lack of response from the Infragistics team, we were forced to rollback to 12.1. After rolling back, everything worked normally.