My xamDataChart displays a number of ScatterSeries and I build a set of custom markers to display on my xamDataChart and would like to get those to show up in the legend. To get the custom markers to show up I essentially created the marker points (e.g., for a square I might do "0,0 1,0 1,1 0,1") and created a polygon template like so:
<DataTemplate x:Key="polygonTemplate">
<Polygon Stretch="Fill" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Fill="{Binding ActualItemBrush}" Points = "{Binding Item.Points}" Stroke="{Binding Series.ActualMarkerOutline}"
MinWidth="10" MinHeight="10" RenderTransform="{Binding Item.RenderTransform}"/>
</DataTemplate>
In the code behind, I build my scatter series.
This works pretty well but my legend doesn't display the polygon badge (I think that's what it is called).
If I create instead an ellipseTemplate which uses an Ellipse, it'll draw pretty well (since I didn't have to bind it to something to get the points that make up the shape. For now, this is what I'm using but I'd like to display my own shapes (rather than an ellipse or the stock shapes).
How would you get the series shape to show up for these custom polygons?
Thanks,
Matt
This sample should give you an idea of both how you can override the badge template for a series, and how you can store additional information about a series to bind against from the badge template.
<Window.Resources> <local:TestData x:Key="data" /> <DataTemplate x:Key="customTemplate"> <Rectangle Width="15" Height="15" Stroke="Black" StrokeThickness="2" Fill="{Binding Path=Series.(local:ChartInfo.LegendBrush)}" /> </DataTemplate> </Window.Resources> <Grid x:Name="LayoutRoot" Background="White"> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <igChart:Legend x:Name="legend1" Grid.Column="1" VerticalAlignment="Top" /> <igChart:XamDataChart x:Name="theChart" Legend="{Binding ElementName=legend1}"> <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 LegendItemBadgeTemplate="{StaticResource customTemplate}" x:Name="series" Title="Series 1" ItemsSource="{StaticResource data}" XAxis="{Binding ElementName=xAxis}" YAxis="{Binding ElementName=yAxis}" ValueMemberPath="Value" local:ChartInfo.LegendBrush="Red" /> <igChart:ColumnSeries LegendItemBadgeTemplate="{StaticResource customTemplate}" x:Name="series2" Title="Series 2" ItemsSource="{StaticResource data}" XAxis="{Binding ElementName=xAxis}" YAxis="{Binding ElementName=yAxis}" ValueMemberPath="Value" local:ChartInfo.LegendBrush="Green" /> <igChart:ColumnSeries LegendItemBadgeTemplate="{StaticResource customTemplate}" x:Name="series3" Title="Series 3" ItemsSource="{StaticResource data}" XAxis="{Binding ElementName=xAxis}" YAxis="{Binding ElementName=yAxis}" ValueMemberPath="Value" local:ChartInfo.LegendBrush="Blue"/> </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 }); Add(new TestDataItem() { Label = "B", Value = 2 }); Add(new TestDataItem() { Label = "C", Value = 3 }); Add(new TestDataItem() { Label = "D", Value = 4 }); } } public class TestDataItem { public string Label { get; set; } public double Value { get; set; } } public class ChartInfo { public static Brush GetLegendBrush(DependencyObject obj) { return (Brush)obj.GetValue(LegendBrushProperty); } public static void SetLegendBrush(DependencyObject obj, Brush value) { obj.SetValue(LegendBrushProperty, value); } public static readonly DependencyProperty LegendBrushProperty = DependencyProperty.RegisterAttached("LegendBrush", typeof(Brush), typeof(ChartInfo)); }
Hope this helps! Sorry about the delay.-Graham
Graham Murray"] Are the points the same for every item in the series? Or do they differ? You could store them in an attached property on the Series and then bind at them on the series.
Are the points the same for every item in the series? Or do they differ? You could store them in an attached property on the Series and then bind at them on the series.
Can you please provide an example of how to do this?
Yes, all of the items for a series are the same shape but individual items might be rendered larger using a RenderTransform (as discussed in other questions I've written).
Sorry for the novice line of questioning but would you be able to give me an example of creating such an attached property in the code behind?
I'm still a bit fuzzy on some of these template and binding ideas.
Right now I've got something like this in the code behind:
Dictionary<int, string> yValToPolyStringDict;
which just holds the series polygon strings (like "0,1 1,1 0.5,1") and I do a lookup when building the series initially and each of the points in the series has a copy of that polygon string. It would be better I'm sure to get out of that situation and have the series hold the polygon info but I wasn't sure how to do that. Is this what you're talking about with the attached property?
How could I specify the static badge for the series instead?
Ultimately, all this comes back to my desire to specify a RenderTransform on points based on a Selected property in the underlying data.
I hope this makes sense.
Matt,
For a series legend item, there is a Series in context, but not an item, because the Legend item is representing all the items in the series. So you can bind to properties on the series, but not on an item. So if you are having the items individually define a shape, that won't be accessible from the legend item badge. Are the points the same for every item in the series? Or do they differ? You could store them in an attached property on the Series and then bind at them on the series. Or you could specify a fallback shape as the fallback value of your binding so that something will get displayed if there is no item in the context.
Also, if you want to manually override the template that a series will use as its legend item badge, you can set one on the LegendItemBadgeTemplate property for the series. For a scatter series, this defaults to trying to use the Marker template. But if your marker template cannot operate without an Item in context. You could specify a static badge to use for the series instead.
Does this explaination help?
-Graham