I'm using a "Custom Heat Map Source" as described here:
https://docs.telerik.com/devtools/wpf/controls/radheatmap/howto/create-custom-heatmap-source
Upon initialization, I fill in the color of all the cells with a default color.
Later, as data comes in, I update the color of individual cells.
It seems that the only way to refresh the Definition so that it will display the newly set cell color is to do the following:
HeatMapDefinition.SelectedItems = new Collection<object>();
After that, the Definition updates itself by calling method "CustomHeatMapDefinition::GetColor()" on each and every cell (which of course gets delegated to the "CustomHeatMapSource" implementation.
This could lead to performance problems on large Heat-Maps.
So my request is that there is a feature allowing the updating of individual cell-data and a refresh mechanism that would not query each heat-map cell afterwards, but only the updated cells.
I have discussed this in a support request (https://www.telerik.com/account/support-tickets/view-ticket/1464531) with Dinko and he suggested I request this feature.
Best,
Mark
Hello Mark,
Thank you for the project and the detailed description.
Indeed, the RedrawCell() method call seems to be not very reliable. That is because the method is called internally on different occassions which reverts the cell color to the one originally returned by the GetColor method of the CustomHeatMapSource. To improve this behavior, you can also update the Color property of the associated CustomHeatMapItem object. For example:
private void RadButton_Click(object sender, RoutedEventArgs e)
{
var color = !wasBlack
? Colors.Black
: Colors.MediumPurple;
wasBlack = !wasBlack;
RedrawCell(2, 2, color);
}
public void RedrawCell(int rowIndex, int columnIndex, Color color)
{
int intColor = CustomHeatMapDefinition.ToColorInt(color);
_redrawMethodInfo.Invoke(_colorGrid, new object[3] { rowIndex, columnIndex, intColor });
this.data[rowIndex, columnIndex].Color = color; // where this.data is the CustomHeatMapItem[,] array
}
About the issue where the cell is not updated immediately, I couldn't manage to reproduce this in my project, so if you can recreate this, don't hesitate to share what I need to update on my side.
Regarding the UpdateCellColor, this is not included in our immediate planning yet, and I am afraid that I cannot give a specific time frame. And for the alternative component, there is no proper solution that would allow to display such a big amount of data in a faster manner than the heatmap. In general, the heatmap is considered relatively fast since it displays a single image for the cells, compared to other components which rely on visual WPF elements rendering. To implement something even faster, you can consider an approach with displaying your own image (using the WPF built-in drawing capabilities or a third party library, like SkiaSharp), which will allow you to redraw only the parts you need manually, but with this idea you will need to manually calculate the cells and also the row and column labels.
For the Priority Support package and the faster responses, I suggest you to use the support ticketing system. This way you can take advantage of the 24h reponse time, compared to the comments section in the feedback portal where you may need to wait more.
Regards,
Martin Ivanov
Progress Telerik
Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.
Hello Martin,
Thanks for your inputs.
Since we have Heatmaps with underlying grids of > 200k cells, I've no other choice other than to use the implementation contained in your post from 20 May 2020 12:04, as updating the entire grid, for each required color-change, is just too slow.
As in your sample-program, when the heat-map loads, in code-behind, I retrieve the HeatMapColorGrid from the Heatmap, and, using reflection, then obtain method
private void HeatMapColorGrid::RedrawCell(int rowIndex, int columnIndex, int intColor)
That works; however, there are effects: The cells that I update with new colors (dynamically, after initial map creation) do not display new colors until I do something like
a) make the app-window full-screen or simply change its size (moving the window has no effect), or
b) move the mouse over the updated cells, or
c) toggle a binding like CellBorderThickness from 1 to 0 and then back to 1
I went back and experimented with your "CustomHeatMapSource.zip". It behaves differently:
When changing the color of cell (2,2), one sees the change, immediately. However - if I then do the things I listed above, i.e. changing the window dimensions or mouse-hover-over, the cell reverts back to the original color!
To summarize the visual effects:
- In my implementation I have to perform a, b, or c to see the new colors.
- In your test-app I see the new color in cell (2,2) immediately, but the color reverts back when doing a or b; c is not implemented.
The implementation of the work-around in our full-up program is exactly the equivalent of yours; however, I have not yet created a Minimal Faulty Program of it, because I see visual effects in your implementation, too.
To eliminate the possibility that the .NET version or the DLL / Nuget version is playing a role, I did go ahead and re-create your customheatmapsource.zip, using the C# sources only. It is a .NET 8 desktop program and uses the "telerik.ui.for.wpf.70\2024.1.130" Nuget, as our full-up program does. I'm uploading this to you here.
Spoiler alert - it displays the exact same visual effects as in your 4-year-old .NET 4.8 version.
I've also uploaded some screen-shots that display the problem in our full-up program.
What we really need is either:
- A better work-around that colors individual cells, on demand, without any visual side-effects and without having to, for instance, toggle the CellBorderThickness binding from 1 and then back to 0, in order to see the new colors, or
- A proper fix:
HeatMapDefinition::UpdateCellColor(int x, int y, int color)"
Since we do have Priority Support, I would be grateful if we could get some quick responses:
- Is there a truly workable "fix" with no visual side-effects?
- What about HeatMapDefinition::UpdateCellColor(int x, int y, int color)"? This was, after all, a reasonable feature-request from four years ago.
- If all else fails, can you suggest an alternative component, from Telerik or otherwise, that can handle 200k cells and does what we need (quick to load, displays cell colors, row & column labels, cell-tooltips, and allows for post-heatmap-instantiation color updates)?
Best Regards,
Mark
Hello Mark,
I can confirm that the situation is still the same. The desired UpdateCell method (or similar) is not yet implemented and your assessment sounds right. The reason behind the missing mehtod is that the planning of features in the Telerik UI for WPF is a complex process that involes multiple factors and this item still cannot enter the queue. I will forward this to the develpment team for review, but cannot give any promises. What I can suggest you is to keep following this item in order to get notified when its status changes.
About the OnItemsSourceChanged abstract method, this is a PropertyChanged callback method invoked when the ItemsSource of the HeatMapDefinition changes. The RadHeatMap's HeatMapDefinition implementations (like CategoricalDefinition) are using this method to sync their ItemsSource with the ItemsSource of the associated IHeatMapSource used by the definition. For example, this is how the CategoricalDefinition uses the method:
protected override void OnItemsSourceChanged()
{
this.source.ItemsSource = this.ItemsSource;
}
Where "this.source" is the IHeatMapSource implementation that works with the CategoricalDefinition.
Note that the method is not limited only to this action. You can implement your own behaviors in your custom HeatMapDefinition that should get executed on ItemsSource changed.
Regards,
Martin Ivanov
Progress Telerik
Hello!
Four years later, and I'm back at the same company working on similar things.
I am still "Mark" although the account e-mail will have changed.
This time, we have a heatmap with 200k+ cells. Part of the colorization occurs when the map is instantiated.
The rest of the colorization occurs during a measurement process.
In summary, we have static and dynamic needs because cell colors & values need to be updated after initial heatmap instantiation.
We're using Nuget "Telerik.UI.for.Wpf.70 (2024.1.130)", and I'm looking at the Heatmap documentation.
Noticeable is that there still is no "UpdateCell(x, y)" method anywhere to be found on the HeatMapDefinition, which could be used to set the color or value of 1 single cell, and subsequently have the heatmap update itself accordingly, in an efficient manner.
So, it seems I have two choices:
Do I assess the situation correctly?
If so, might I ask why the seemingly useful method "UpdateCell()" has not been added to the HeatMapDefinition?
----> Also: In "HeatMapDefinition" there exists method
protected abstract void OnItemsSourceChanged();
How should it be used?
Best,
Mark
Hello Mark,
HeatMapColorGrid is the panel that draws the cells in the RadHeatMap control. You are correct, HeatMapColorGrid uses the heatmap definition.
Regards,
Martin Ivanov
Progress Telerik
Hello Martin,
Thank you for your inputs.
I assume that the "HeatMapColorGrid" is that object that uses the "CustomHeatMapDefinition"?
As a work-around that would probably work; I'm not sure if I will get that through a GitHup review, though.
Thanks!
Best,
Mark
Hello Mark,
I am attaching a modified version of the CustomHeatMapSource SDK example that shows how to color only a specific cell by its row and column index. I hope that helps.
Regards,
Martin Ivanov
Progress Telerik
Hello Mark,
Thank you for confirming this. We approved this feature request. Also, I've twitched the title a bit in order to be a bit more general.
Regards,
Martin Ivanov
Progress Telerik
Hello Martin,
Yes, that is correct.
Thanks,
Mark
Hello Mark,
Thank you for the suggestion. This sounds meaningful but before proceeding with changing its status, may I ask you to confirm if I got it properly? So, at some point in time, you need the color of the a particular cell to change and you need an API that allows you to change a specific area (the updated cell) of the generated Bitmap image instead of iterating all cells and redrawing the picture from scratch. Is this correct?
Regards,
Martin Ivanov
Progress Telerik