This thread looks to be a little on the old side and therefore may no longer be relevant. Please see if there is a newer thread on the subject and ensure you're using the most recent build of any software if your question regards a particular product.
This thread has been locked and is no longer accepting new posts, if you have a question regarding this topic please email us at support@mindscape.co.nz
|
Is it possible to make a legend oriented vertically? Something like the attachment, that could go to the right of a chart? Specifically I'm using the heatmap chart in WpfElements v6.0.2594.23080 |
|
|
Hello Thanks for your interest in our WPF Heatmap chart. It is certainly possible to create a vertical heatmap legend. In the code demo on the Heatmap blog post, you will see the legend was mostly constructed in the application by using styles and templates in the resource dictionary. Here is a modification of that code which creates a vertical Heatmap legend similar to the image you posted:
At the top we have the base legend item template. This is for displaying the legend icon for the series and the title of the legend. This is a copy of the legend item template from our Generic.xaml file for the charts. Since you may not want to display the title for this kind of vertical legend, I have commented out the label. You could add this back in or reposition it if you like. Next is the legend style, this mostly sets some basic properties, hides the "Legend" header, and also applies the item template that I mentioned above. Next is a converter and the template for displaying the heatmap gradient. The HeatmapGradientConverter is provided by WPF Elements. Since the heatmap gradient brush you provide will contain the actual values (in your case -32768 to 32767), this converter normalizes the values to a range of 0 to 1 which is required for displaying in an actual gradient brush. Here you will see I'm setting the Orientation of the converter to vertical. This is a new property that I've added for you, so you'll need to get the next nightly build in order to use this too. The icon template is fairly simple. It has 2 columns: one with the gradient border that gets the color values from the Heatmap series, and the other column with hard coded labels. For your legend, you could either add more labels to get the same look as the image that you posted, or you could create a converter that reads the Offset values from the HeatmapSeries SeriesBrush property to make it more reusable and easier to maintain. Now, to apply all this, you set the LegendStyle property of the Chart control to be the LegendStyle in the above code, and you set the LegendIconTemplate of the HeatmapSeries to be the HeatmapSeriesLegendIcon. And last of all, you'd want to set the LegendPosition property of the Chart control to be Right. Please let me know if you have questions about any of this. -Jason Fauchelle |
|
|
Never mind, duh, you clearly stated I need to get the next nightly build. Hi Jason, In the line Thanks! Leah |
|
|
You said "For your legend, you could either add more labels to get the same look as the image that you posted, or you could create a converter that reads the Offset values from the HeatmapSeries SeriesBrush property to make it more reusable and easier to maintain." Adding labels isn't giving me what I want, so how would I create a converter? I see the GradientStop Offset values in the LinearGradientBrush, but don't understand what you mean about the converter. What I am trying to do is read in different color maps so the user can change how the map is displayed. Each color map consists of 64 colors, so in my LinearGradientBrush (xaml), I have 64 GradientStops with the Color bound to each of the 64 colors in my map files. Having 64 lines in my XAML is probably not ideal, but it allows me to change the color maps. However, my data doesn't look quite right because I'm not sure how to set the Offsets and I also don't see how to get the legend to display certain values (say the 0th, 16th, 31st, 48th, and 63rd items). I was thinking about binding the Offsets based on the min/max, but will the converter do something automagically for me that will handle the legend based on the offsets? |
|
|
Hello Leah Here is a description of roughly what I meant about using a converter to display labels: 1/ Create a new class called HeatmapLegendLabel. This will represent each label displayed against the gradient and will have a value and a position.
2/ Next, create a new class called HeatmapLegendLabelsConverter. This class will implement IMultiValueConverter which will accept the gradient brush, and the height of the legend icon so that it can also do all the label positioning logic. Here is a possible implementation of the Convert method:
This method requires the gradient brush to have at least 2 gradient stops, and assumes that they are in offset-order. First, it calculates the logical range of the gradient by getting the difference between the first and last offsets. Next, it calculates the logical to pixel conversion ratio. Next, I've created a very simple loop that will create 4 evenly spaced labels. For each label, I get an interpolated offset value between the min and max offsets, and then calculate the pixel position by multiplying the offset value with the conversion ratio. These two things (offset and position) are the two things required to make the legend labels. 3/ Then you will need to update the legend icon template:
First off is an instance of your new converter, along with the converter you already know of. Next is a template to display the labels. This is a TextBlock binding to the Value property, and uses a TranslateTransform binding to the Position property. In the Value binding, you could include a StringFormat to customize the format of the labels (set number of decimal places or add unit symbols etc). In the icon template, you will see I've replaced the hard coded labels with an ItemsControl. The ItemsSource uses a multibinding with the new converter to convert the gradient brush and the height of the gradient display into the list of labels. Make sure to set the ItemsPanel property to be a Grid or Canvas so that the labels are not managed by any layout and thus can be positioned with the translate transform I mentioned earlier. I've also set the margin of the ItemsControl to shift it up 10 pixels. This is so that each label appears "centred" with the value that it actually displays against the gradient rectangle. The value of this margin will depend on the font size you are using for the labels. Play around with the values to see what I mean. 4/ Last of all, you can update the converter to have whatever logic you need. You could adjust it so there are more labels displayed. Or you could use the given size value to automatically calculate a suitable number of labels to display. Or, rather than a loop that creates evenly interpolated offset labels, you could display specific gradient stops from the brush itself like you mentioned. The offset values you use in the gradient brush will be based on the values of your data. You will need to know the rough range of possible data to work out what offset value to use. Basically, the heatmap will get the color of each point by interpolating the gradient stops with the data value. This should point you in the right direction for implementing the heatmap legend label logic you need for your application. Let me know if you have questions about any of this. -Jason Fauchelle |
|
|
Hi Jason, I got this all to work, thanks!! For the HeatmapGradientConverter, with the vertical orientation, the min value is showing at the top of the legend, and the max value is showing at the bottom of the legend. This is because my min/max offsets are set like this, and have to be set like this in order to show my data correctly.
However, I'd like the min value to show at the BOTTOM of the legend and the max value to show at the TOP, is this possible? I tried switching the order of my offsets in the XAML, which makes the legend show like I want, but that also flips the colors in the heatmap and I don't want that. I've tried all different combinations of the color and the offset in the XAML to no avail. The attached image shows what I mean. Can I flip the vertical legend? |
|
|
Hello Leah Sorry about that, the converter code I sent was faulty. The gradient converter DOES put the colors from lowest at the bottom to highest at the top (based on the offsets), but the label converter was reversed. You can resolve this by going to the HeatmapLegendLabelsConverter class and where you instantiate the HeatmapLegendLabel, set the Position to: size - position. You should find that you've set -2000 to white, and 5000 is black. -Jason Fauchelle |
|