Jump to content
Software FX Community

MVVM ItemsSource updated but graph concatenates data...


Recommended Posts

I am trying to use the chart with a MVVM pattern.  I have a ObservableCollection of objects that store data for the chart.  This data works well with the chart, but I want to allow the user to change date ranges by selecting from a set of radio buttons.  I have it working that when the user selects the radio button the ViewModel's ObservableCollection updates.  The problem is when the ObservableCollection updates and the PropertyChanged notification is raised the Graph concatenates the new data with the old data instead of showing the new data...  Not sure if there is the way, using a MVVM pattern, to get the ItemsSource for the chart to update without having to handle the SourceUpdated event in the code behind. 

I would prefer to keep code out of the code behind file since it violates the MVVM pattern and makes it harder to test our ViewModels.  I have attached the XAML and the ViewModel code that the UserControl is bound to.  Not sure if it will compile since I remove some markup and code... :)

 Here is the XAML... 

<UserControl x:Class="Summary.Views.SummaryView" xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml xmlns:ViewModels="clr-namespace:Summary.ViewModels" xmlns:cfx=http://schemas.softwarefx.com/chartfx/wpf/80 xmlns:cfxconverters=http://schemas.softwarefx.com/chartfx/wpf/80/converters xmlns:cfxcontrols=http://schemas.softwarefx.com/chartfx/wpf/80/controls xmlns:cfx3d=http://schemas.softwarefx.com/chartfx/wpf/80/drawing3d xmlns:cfxmotifs=http://schemas.softwarefx.com/chartfx/wpf/80/motifs >


<ControlTemplate x:Key="ChartControlTemplate1" TargetType="{x:Type cfx:Chart}">   <cfx:ChartBorder>   <Border Margin="0,0,0,0" Background="#FFE6E6E6" CornerRadius="3,3,3,3">   <cfxcontrols:SpacingDockPanel cfx:Chart.PanelName="Tools,Titles,Plot" SpacingDockStrategy="ApplySpacing" Margin="6,6,6,6"/>   </Border> </cfx:ChartBorder> </ControlTemplate> </UserControl.Resources> <UserControl.DataContext>   <ViewModels:InstallationSummaryDashboardViewModel/> </UserControl.DataContext> <Border>   <Grid>   <Grid.RowDefinitions>   <RowDefinition Height="Auto"/>   <RowDefinition Height="*"/>   </Grid.RowDefinitions>   <Grid>     <ItemsControl ItemsSource="{Binding Path=ReportRangeRadioButtons}">   <ItemsControl.ItemTemplate>   <DataTemplate>   <RadioButton Content="{Binding Path=DisplayName}" IsChecked="{Binding Path=IsChecked, Mode=TwoWay}" Style="{DynamicResource ItronRadioButtonStyle}" GroupName="GraphRadioGroup"/>   </DataTemplate>   </ItemsControl.ItemTemplate>   </ItemsControl>     <cfx:Chart x:Name="InstallationGraph" ItemsSource="{Binding Path=InstallationRateData}" Gallery="Line" Style="{x:Static cfxmotifs:Basic.Style}" Template="{DynamicResource ChartControlTemplate1}" Margin="4,4,0,0" Grid.Row="1">   <cfx:Chart.Titles>   <cfx:Title Content="Installation Rate (NL)"/>   </cfx:Chart.Titles>   <cfx:Chart.AxisY>   <cfx:Axis>   <cfx:Axis.Title>   <cfx:Title Content="Count (NL)"/>   </cfx:Axis.Title>   </cfx:Axis>   </cfx:Chart.AxisY>   <cfx:Chart.AxisX>   <cfx:Axis>   <cfx:Axis.Labels>   <cfx:AxisLabelAttributes BindingPath="Date" Format="Date"/>   </cfx:Axis.Labels>   <cfx:Axis.Title>   <cfx:Title Content="Dates (NL)"/>   </cfx:Axis.Title>   </cfx:Axis>   </cfx:Chart.AxisX>   <cfx:Chart.Series>   <cfx:SeriesAttributes BindingPath="Actual" Content="Actual (NL)"/>   <cfx:SeriesAttributes BindingPath="Planned" Content="Planned (NL)"/>   <cfx:SeriesAttributes BindingPath="Baseline" Content="Baseline (NL)"/>   </cfx:Chart.Series> </cfx:Chart>   </Grid> </Border> </UserControl>


namespace Summary.ViewModels {   public class SummaryViewModel : ViewModelBase   {   public SummaryViewModel()   {   CreateReportRangeRadioButtons();   }   private ObservableCollection<InstallationDateViewModel> _InstallationRateData;   public ObservableCollection<InstallationDateViewModel> InstallationRateData   {   get { return _InstallationRateData; }   set   {   if (_InstallationRateData != value)   {  //Set it and raise the property changed event...   _InstallationRateData = value;   OnPropertyChanged("InstallationRateData");   }   }   }   public ObservableCollection<InstallationRadioButtonViewModel> ReportRangeRadioButtons { get; set; }   private void CreateReportRangeRadioButtons()   {   InstallationRadioButtonViewModel radioButton; ReportRangeRadioButtons = new ObservableCollection<InstallationRadioButtonViewModel>();     radioButton = new InstallationRadioButtonViewModel() { DisplayName = Properties.Resources.Resources.UI_WPF_Dashboard_ProjectToDate, IsChecked = true, GraphType = GraphType.ProjectToDate };   CreateInstallationRateData(radioButton.Range);   radioButton.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(radioButton_PropertyChanged);   ReportRangeRadioButtons.Add(radioButton);   radioButton = new InstallationRadioButtonViewModel() { DisplayName = Properties.Resources.Resources.UI_WPF_Dashboard_RollingThirtyDays, IsChecked = false, GraphType = GraphType.Rolling30DayWindow };   radioButton.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(radioButton_PropertyChanged);   ReportRangeRadioButtons.Add(radioButton);   radioButton = new InstallationRadioButtonViewModel() { DisplayName = Properties.Resources.Resources.UI_WPF_Dashboard_LastSixMonths, IsChecked = false, GraphType = GraphType.LastSixMonths };   radioButton.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(radioButton_PropertyChanged);   ReportRangeRadioButtons.Add(radioButton);   }   //When the InstallationRadioButtonViewModel's IsChecked bool changes I get the range from it and create the installation rate data...   void radioButton_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)   {   if (e.PropertyName == "IsChecked")   {   CreateInstallationRateData(((InstallationRadioButtonViewModel)sender).Range);   }   }   private void CreateInstallationRateData(double days)   {   //The data that is bound to the charts ItemsSource is nulled this should raise the PropertyChanged notification   if (InstallationRateData != null)   {   InstallationRateData = null;   }  //Then I new it...   InstallationRateData = new ObservableCollection<InstallationDateViewModel>();   Random random = new Random();   DateTime startDate = DateTime.Now;   startDate.AddDays(days);   int startActual = 10;   int startPlanned = 10;   int startBaseline = 10;   //And then fill it...   for (int i = 0; i < (int)Math.Abs(days); i++)   {   InstallationRateData.Add(new InstallationDateViewModel() { Date = startDate, Actual = startActual, Planned = startPlanned, Baseline = startBaseline });   startDate = startDate.AddDays(1);   startActual = random.Next(0, 1000);   startPlanned = random.Next(0, 1000);   startBaseline = random.Next(0, 1000);   }   }   int RandomNumber(int min, int max)   {   Random random = new Random();   return random.Next(min, max);   }   }}

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Create New...