This is a migrated thread and some comments may be shown as answers.

Extending RadChart for better MVVM binding

10 Answers 263 Views
Chart
This is a migrated thread and some comments may be shown as answers.
Andre
Top achievements
Rank 1
Andre asked on 21 Feb 2011, 10:40 PM
Hello,

I'm trying to extend RadChart to use the same approach of MultChart, one Binding variable (IEnumerable of IEnumerable) and a datatemplate to define the data series.
I would like to have no references of telerik in my viewmodel.
The problem is that no matter what I bind to the chart control, I get a bar chart with unknown data :(
Would you be so nice to take a look on it for me?
The code I'm working with can be found here: [buggy code removed]

Thank you in advance,
André Carlucci


10 Answers, 1 is accepted

Sort by
0
Andre
Top achievements
Rank 1
answered on 22 Feb 2011, 08:55 PM
I did it!

RadChart with multichart binding using DataTemplateSelector working like a charm :)

The main idea came from here: http://blog.thekieners.com/2010/02/07/databinding-multi-series-charts/

Now I can declare a chart like this:

<UserControl.Resources>
        <TelerikChart:SeriesTemplateSelector x:Key="chartTemplateSelector">
            <TelerikChart:SeriesTemplateSelector.BarChart>
                <DataTemplate>
                    <TelerikChart:DataTemplateSeriesMapping>
                        <TelerikChart:DataTemplateSeriesMapping.SeriesDefinition>
                            <telerik:BarSeriesDefinition ShowItemLabels="False" />
                        </TelerikChart:DataTemplateSeriesMapping.SeriesDefinition>
 
                        <TelerikChart:DataTemplateSeriesMapping.ItemMappings>
                            <telerik:ItemMapping FieldName="Value" DataPointMember="YValue" />
                            <telerik:ItemMapping FieldName="Date" DataPointMember="XValue" />
                        </TelerikChart:DataTemplateSeriesMapping.ItemMappings>
 
                    </TelerikChart:DataTemplateSeriesMapping>
                </DataTemplate>
            </TelerikChart:SeriesTemplateSelector.BarChart>
 
            <TelerikChart:SeriesTemplateSelector.LineChart>
                <DataTemplate>
                    <TelerikChart:DataTemplateSeriesMapping>
                        <TelerikChart:DataTemplateSeriesMapping.SeriesDefinition>
                            <telerik:LineSeriesDefinition ShowItemLabels="False" />
                        </TelerikChart:DataTemplateSeriesMapping.SeriesDefinition>

                        <TelerikChart:DataTemplateSeriesMapping.ItemMappings>
                            <telerik:ItemMapping FieldName="Value" DataPointMember="YValue" />
                            <telerik:ItemMapping FieldName="Date" DataPointMember="XValue" />
                        </TelerikChart:DataTemplateSeriesMapping.ItemMappings>
 
                    </TelerikChart:DataTemplateSeriesMapping>
                </DataTemplate>
            </TelerikChart:SeriesTemplateSelector.LineChart>
        </TelerikChart:SeriesTemplateSelector>
 
    </UserControl.Resources>

     <TelerikChart:MvvmRadChart SeriesSource="{Binding Curves}"
                                SeriesTemplateSelector="{StaticResource chartTemplateSelector}" />


And it works perfectly :)

If you are interested in the source code just tell me and I will be more than happy to share.

Cheers,

AndrĂ© Carlucci 
0
Nathan
Top achievements
Rank 1
answered on 25 Feb 2011, 07:29 PM
Very interested!

Thanks, Andre
0
Andre
Top achievements
Rank 1
answered on 01 Mar 2011, 02:25 PM
Hi Nathan,

I've uploaded the whole project to http://www.telerik.com/community/code-library/silverlight/chart.aspx, but it's not there yet. I guess they have some kind of moderation, so let's wait to see.

Cheers,

André Carlucci
0
Vladimir Milev
Telerik team
answered on 03 Mar 2011, 12:26 PM
Hello Andre,

We just published the code library. Please, note our comments below the submission.

Best wishes,
Vladimir Milev
the Telerik team
Registration for Q1 2011 What’s New Webinar Week is now open. Mark your calendar for the week starting March 21st and book your seat for a walk through all the exciting stuff we ship with the new release!
0
David
Top achievements
Rank 1
answered on 22 Mar 2011, 12:29 PM
Andre - really nice work, thanks!
I am currently evaluating RadControls vs DevExpress right now and this is another reason to switch.

Have you got the LegendLabel to be able to bind to a string value in the ChartInfo object? (that looks like what you were aiming for)

0
Andre
Top achievements
Rank 1
answered on 22 Mar 2011, 01:51 PM
Hi David,

Yes I did.

Here is one exemple of a DataTemplate with LegendLabel:

 <DataTemplate>
                    <TelerikChart:SeriesMappingWrapper ChartAreaName="chartArea" LegendLabel="{Binding Title}" >
 
                        <TelerikChart:SeriesMappingWrapper.SeriesDefinition>
                            <telerikCharting:BarSeriesDefinition ShowItemLabels="False" />
                        </TelerikChart:SeriesMappingWrapper.SeriesDefinition>
 
                        <TelerikChart:SeriesMappingWrapper.ItemMappings>
                            <telerikCharting:ItemMapping FieldName="Value" DataPointMember="YValue" />
                            <telerikCharting:ItemMapping FieldName="Date" DataPointMember="XValue" />
                        </TelerikChart:SeriesMappingWrapper.ItemMappings>
 
                    </TelerikChart:SeriesMappingWrapper>
                </DataTemplate>

Cheers :)
0
David
Top achievements
Rank 1
answered on 22 Mar 2011, 02:26 PM
Yes, that's what I assumed, however it didn't work when I tried that. Perhaps you have code in the wrapper different to that you submitted to Telerik?

You set the datacontext for each SeriesMappingWrapper in the CreateSeriesMapping and then grab the SeriesMapping straight out of it (in the code I have).
templateSeriesMapping.DataContext = dataContextForSerie;
return templateSeriesMapping.SeriesMapping;
 I would have thought that the act of setting the DataContext would cause the dependencyproperties to get their values (in particular the LegendLabel one) , but this doesn't seem to happen. I wonder if I need to force the binding update to happen somehow? (so that the OnLegendLabelChanged handler gets called)

Apologies if this is a stupid question, i'm a little new to WPF.
0
Andre
Top achievements
Rank 1
answered on 23 Mar 2011, 08:42 PM
Hi David,

The code I'm using is the same :(
The thing is that when you set the dataContext, nothing really happens with the bindings at that moment.
The bindings will be enforced once the control gets "loaded" or every time you call NotifyPropertyChanged event on the property you want to update.
So, if you want to update the legend value after the object creation or at run time, make ChartInfo implement INotifyPropertyChanged interface and raise the PropertyChanged event with the LegendLabel property. It should work :)

Cheers,

André Carlucci
0
Graham Ramsay
Top achievements
Rank 1
answered on 24 Mar 2011, 11:35 PM
Love what you done with it so far, but I am running into a scoping problem around the DataContext I believe.  What I would like to do given the examples you've provided is to allow the ShowItemLabels property of the SeriesDefinition to be defined by a binding, but it does not work.   So similar to your template above, I'd like a template option with this XAML (you'll notice the only real significant change is that the ShowItemLabels property in the series wrapper is set to a binding rather than false):
 

 

 

 

 

 

<TelerikChart:SeriesTemplateSelector.LineChart>
                    <DataTemplate>
                        <TelerikChart:SeriesMappingWrapper ChartAreaName="chartArea">
                            <TelerikChart:SeriesMappingWrapper.SeriesDefinition>
                                <telerik:LineSeriesDefinition ShowItemLabels="{Binding DisplayDataLabels}"/>
                            </TelerikChart:SeriesMappingWrapper.SeriesDefinition>
  
                            <TelerikChart:SeriesMappingWrapper.ItemMappings>
                                <telerik:ItemMapping FieldName="Value" DataPointMember="YValue" />
                                <telerik:ItemMapping FieldName="TimePoint" DataPointMember="XValue" />
                            </TelerikChart:SeriesMappingWrapper.ItemMappings>
  
                        </TelerikChart:SeriesMappingWrapper>
                    </DataTemplate>
                </TelerikChart:SeriesTemplateSelector.LineChart>

 

 

 

 

 

 


But this doesn't work, as when the framework processes the Binding statement the DataContext scope is the whole ViewModel of my UI rather than the item in the collection that I am binding to the ItemSource.  Any ideas how to achieve this behavior?  In the end my requirement is to show series labels on some series, but not on every series.

I've seen in your example you set the DataContext of the SeriesMappingWrapper to be the item in the collection you'd like for that series, and the ItemMappings DataContext scope seems correct as it does draw the data.  But can't figure out why the nested SeriesDefinition doesn't have same DataContext scope.

My collection that is assigned to Chart ItemSource supports INotifyPropertyChanged and is a derived ObservableCollection, and each nested object in that collection also supports INotifyPropertyChanged and is a derived ObservableCollection.

Thanks,

Graham Ramsay
0
Andre
Top achievements
Rank 1
answered on 25 Mar 2011, 03:57 PM
Hi Graham,

I understand your problem.
Since SeriesDefinition is also not a FrameworkElement, you cannot set its DataContext. I don't know exactly why it's not getting it from SeriesMappingWrapper :(

One thing you can do is create another wrapper for the SeriesDefinition and use the same SeriesMappingWrapper strategy. Then you can set the SeriesDefinition DataContext programmatically. 

It's too bad we have DependencyObjects instead of FrameworkElements everywhere, but that's a Telerik issue.

Cheers,

André
Tags
Chart
Asked by
Andre
Top achievements
Rank 1
Answers by
Andre
Top achievements
Rank 1
Nathan
Top achievements
Rank 1
Vladimir Milev
Telerik team
David
Top achievements
Rank 1
Graham Ramsay
Top achievements
Rank 1
Share this question
or