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

Creating separate series for ViewModel with multiple properties

4 Answers 168 Views
ChartView
This is a migrated thread and some comments may be shown as answers.
Brandon
Top achievements
Rank 1
Veteran
Brandon asked on 19 Jul 2020, 02:56 AM

I have a ViewModel object with multiple properties I want to plot (such as Value1 and Value2 in DualSample below).  I currently have this working with a SeriesProvider that includes a different SeriesDescriptor and ValueBinding for each property, but using the same ItemsSourcePath.

 

However, I now have some data sets to plot that have a different sample arrangement (such as only having Value1 in SingleSample, and missing Value2).  If I try to use the existing SeriesProvider definition, I get an exception because the SensorValue2Binding doesn't work since the sample is a different type.  I was going to change this to use a SeriesDescriptorSelector, but I don't see how to get multiple series from a single ViewModel  object as before.  The only solution I see is to create separate lists for each property I want to plot, but I'd rather avoid that is I can, mostly to help save on memory usage. 

ViewModel definition:

public interface ISample
{
}
 
// Would like to plot this on the same chart as DualSample
public class SingleSample : ISample
{
    public Double Value1;
    public DateTime Timestamp;
}
 
// This is currently working
public class DualSample : ISample
{
    public Double Value1;
    public Double Value2;
    public DateTime Timestamp;
}
 
public class Sensor
{
    // A Sensor might have a set of DualSample values, or a set of SingleSample values, but not both.
    public ObservableCollection<ISample> SensorData;
}

 

Currently working solution for DualSample only:

<!-- Existing solution that working with DualSample only -->
<telerik:RadCartesianChart.SeriesProvider>
    <telerik:ChartSeriesProvider Source="{Binding SensorList}">
        <!-- When SensorData includes DualSample values, both series descriptors below are used,
        so I get series for both Value1 and Value2 -->
        <telerik:ChartSeriesProvider.SeriesDescriptors>
            <telerik:CategoricalSeriesDescriptor ItemsSourcePath="SensorData">
                <telerik:CategoricalSeriesDescriptor.Style>
                    <Style TargetType="telerik:LineSeries"
                           BasedOn="{StaticResource {x:Type telerik:LineSeries}}">
                        <Setter Property="ValueBinding"
                                Value="{StaticResource SensorValue1Binding}"/>
                        <Setter Property="VerticalAxis"
                                Value="{StaticResource Value1Axis}"/>                                               
                    </Style>
                </telerik:CategoricalSeriesDescriptor.Style>
            </telerik:CategoricalSeriesDescriptor>
 
            <!-- If I have a SensorData collection of SingleSamples, the SensorValue2Binding values
            and the plot crashes with the following ArgumentException:
            "The value Telerik.Windows.Controls.ChartView.LineSeries is not of type
            Telerik.Windows.Controls.ChartView.CartesianSeries and cannot be used in this generic collection"
            <telerik:CategoricalSeriesDescriptor ItemsSourcePath="SensorData">
                <telerik:CategoricalSeriesDescriptor.Style>
                    <Style TargetType="telerik:LineSeries"
                           BasedOn="{StaticResource {x:Type telerik:LineSeries}}">
                        <Setter Property="ValueBinding"
                                Value="{StaticResource SensorValue2Binding}"/>
                        <Setter Property="VerticalAxis"
                                Value="{StaticResource Value2Axis}"/>
                    </Style>
                </telerik:CategoricalSeriesDescriptor.Style>
            </telerik:CategoricalSeriesDescriptor>
        </telerik:ChartSeriesProvider.SeriesDescriptors>
    </telerik:ChartSeriesProvider>
</telerik:RadCartesianChart.SeriesProvider>

 

 

Attempted solution to work with both DualSample and SingleSample:

<!-- Attempted solution that I would like to work with both DualSample and SingleSample data sets -->
<telerik:RadCartesianChart.SeriesProvider>
    <telerik:ChartSeriesProvider Source="{Binding SensorList}">
        <telerik:ChartSeriesProvider.SeriesDescriptorSelector>
            <local:MySeriesDescriptorSelector>
                <local:MySeriesDescriptorSelector.Value1SeriesDescriptor>
                    <telerik:CategoricalSeriesDescriptor ItemsSourcePath="SensorData">
                        <telerik:CategoricalSeriesDescriptor.Style>
                            <Style TargetType="telerik:LineSeries"
                                   BasedOn="{StaticResource {x:Type telerik:LineSeries}}">
                                <Setter Property="ValueBinding"
                                        Value="{StaticResource SensorValue1Binding}"/>
                                <Setter Property="VerticalAxis"
                                        Value="{StaticResource Value1Axis}"/>
                            </Style>
                        </telerik:CategoricalSeriesDescriptor.Style>
                    </telerik:CategoricalSeriesDescriptor>
                </local:MySeriesDescriptorSelector.Value1SeriesDescriptor>
                <local:MySeriesDescriptorSelector.Value2SeriesDescriptor>
                    <telerik:CategoricalSeriesDescriptor ItemsSourcePath="SensorData">
                        <telerik:CategoricalSeriesDescriptor.Style>
                            <Style TargetType="telerik:LineSeries"
                                   BasedOn="{StaticResource {x:Type telerik:LineSeries}}">
                                <Setter Property="ValueBinding"
                                        Value="{StaticResource SensorValue2Binding}"/>
                                <Setter Property="VerticalAxis"
                                        Value="{StaticResource Value2Axis}"/>
                            </Style>
                        </telerik:CategoricalSeriesDescriptor.Style>
                    </telerik:CategoricalSeriesDescriptor>
                </local:MySeriesDescriptorSelector.Value2SeriesDescriptor>
            </local:MySeriesDescriptorSelector>
        </telerik:ChartSeriesProvider.SeriesDescriptorSelector>
    </telerik:ChartSeriesProvider>
</telerik:RadCartesianChart.SeriesProvider>

 

Any suggestions?  Or is my only option to extract my Value1 and Value2 properties into separate lists?

4 Answers, 1 is accepted

Sort by
0
Martin Ivanov
Telerik team
answered on 22 Jul 2020, 02:18 PM

Hello Brandon,

To achieve your requirement, you can create a custom SeriesDescriptor and override its CreateInstanceCore. In the method override, you can get the current ISamle object and based on its concrete type, set the ValueBinding and CategoryBinding methods of the series manually. For example:

public class CustomCategoricalSeriesDescriptor : CategoricalSeriesDescriptor
{
	protected override ChartSeries CreateInstanceCore(object context)
	{
		// create a new series and based on the "context" object, set its ValueBinding and CategoryBinding properties
		return base.CreateInstanceCore(context);
	}
}

I hope this helps.

Regards,
Martin Ivanov
Progress Telerik

0
Brandon
Top achievements
Rank 1
Veteran
answered on 27 Jul 2020, 10:15 PM

Martin,

 

I'm still a little confused on how to make to make this work.  The "context" passed into CustomCategoricalSeriesDescriptor is of type Sensor, which contains my collection or either SingleSample or DualSample instances.  In the case of DualSample, I need to create 2 series (one for Value1 data, another for Value2 data).  Do I need 2 separate series descriptor implementations, one that returns a Value1Series and another that returns a Value2Series?

Also, when CreateInstanceCore() is called, I may not have any data in my collection yet, so I won't know which series I need to return yet.

Since some cases only need 1 series and others need 2, I assumed I would use the SeriesDescriptorSelector, but I don't see how to use this to select multiple series for a given ViewModel type (1 series for SingleSample collections, 2 series for DualSample collections).

 

Is there a different way I need to structure my data in order to get the effect I'm looking for?

 

Thanks,

Brandon

0
Accepted
Martin Ivanov
Telerik team
answered on 30 Jul 2020, 03:56 PM

Hello Brandon,

Thank you for the additional information. It seems that I misunderstood the requirement. The SeriesProvider cannot be setup as per your needs with the current data models structure. To achieve your requirement, you can change the models a bit. Basically, you can add two collections in the Sensor class - one for Value1 and one for Value2. I've prepared a small example showing this approach. I hope it helps.

Regards,
Martin Ivanov
Progress Telerik

0
Brandon
Top achievements
Rank 1
Veteran
answered on 30 Jul 2020, 05:57 PM

Martin,

 

Thanks for your response. The separate collections is what I figured I would have to do, thank you for confirming that.

 

Brandon

Tags
ChartView
Asked by
Brandon
Top achievements
Rank 1
Veteran
Answers by
Martin Ivanov
Telerik team
Brandon
Top achievements
Rank 1
Veteran
Share this question
or