Search code examples
c#wpfmvvm.net-coreoxyplot

Can you bind multiple LineSeries to an oxyplot in WPF using MVVM pattern?


I am trying to plot multiple LineSeries elements in one <oxy:PlotView /> element in WPF using C# in Oxyplot where I am using the MVVM pattern. Say I have the (hypothetical) situation that I am tracking cars with a position as a function of time. Say I have the following files:

  • Model
    • Car.cs
  • View
    • DisplayView.xaml
    • DisplayView.xaml.cs
  • ViewModel
    • DisplayViewModel.cs

On initialization I create three car elements (in DisplayViewModel.cs : Cars = new List<Car>{ new Car(), ...};) with their corresponding displacement vs. time data PlotData = new List<DataPoint>{ new DataPoint(0,1), new DataPoint(1,4), ...}; and CarName.

DisplayView.xaml (1):

<ListBox ItemsSource="{Binding Path=Cars}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <oxy:Plot Title="{Binding CarName}" Height="400" Width="500">
                    <oxy:Plot.Series>
                        <oxy:LineSeries ItemsSource="{Binding Path=PlotData}"/>
                    </oxy:Plot.Series>
                </oxy:Plot>
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

This works as expected. It shows a <ListBox /> with the three (separate) graphs. However this is not what I am trying to achieve. I would like to do something like the following:

DisplayView.xaml (2):

<ItemsControl ItemsSource="{Binding Path=Cars}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Path=CarName}" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

This displays the three individual car names as is expected, so I know I have the data source connected correctly. However, wrapping this <ItemsControl>...</ItemsControl> element with <oxy:Plot><oxy:Plot.Series>...</oxy:Plot.Series></oxy:Plot> and changing the <TextBlock /> element to a <oxy:LineSeries /> element and binding its ItemsSource property to the earlier mentioned DataPoint field yields the errors A value of type 'ItemsControl' cannot be added to a collection or dictionary of type 'collection`1'. and The specified value cannot be assigned to the collection. The following type was expected: "Series"..

DisplayView.xaml (doesn't work):

<oxy:Plot Title="Displacement plot">
    <oxy:Plot.Series>
        <ItemsControl ItemsSource="{Binding Path=Cars}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <oxy:LineSeries ItemsSource="{Binding Path=PlotData}"/>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </oxy:Plot.Series>
</oxy:Plot>

I am new to the MVVM pattern - and C# and WPF programming in general - and I see the DisplayView.xaml.cs code-behind file needs to be empty. I can get the three LineSeries to display in one graph when using the code behind, but I am trying to utilize the power of MVVM. Can someone give me pointers on how I should fix this? I am just not experienced enough (yet) to play around with the code, so some explanation would be appreciated. What files do I need to add, what methods do I need to create and where do I create these? Is this even possible in the way I envision?

Kind regards,

Tom


Solution

  • I think I grasp the concept (after writing down my thoughts and questions in this post), so I am answering my own question. In DisplayView.xaml I added a <PlotView /> as such: <oxy:PlotView x:Name="DisplayPlotView" Model="{Binding PlotModel}" />. I also created a PlotModel in DisplayViewModel.cs, which is fine by the MVVM-pattern, as far as I understand. I loop through Cars to add the different series by doing:

    foreach(Car car in Cars)
        {
            PlotModel.Series.Add(car.PlotData);
        }
    

    Where I now made the PlotData a LineSeries in the Car.cs. This shows the three lines in one graph.