Binding to a data source from two different views. MVVM, WPF

1

So here is the setup. I have two different WPF views. StandardEngineeredView and StandardEngineeredPrintView. I have an ObservableCollection called ModelRevisionList in my StandardEngineeredViewModel.

What I am doing is trying to bind to the ModelRevisionList data source from two different views. I have the data context of my views set to the same view model. There is a button in my StandardEngineeredView that navigates me to the StandardEngineeredPrintView. This second view will essentially just be used to allow someone to print data. Note I have several other properties I will be binding to in the view model from both views. I just have not attempted to do so yet because when trying to bind to the revision List I get the following error:

System.Windows.Markup.XamlParseException HResult=0x80131501 Message='Add value to collection of type 'System.Windows.Controls.ItemCollection' threw an exception.' Line number '204' and line position '55'. Source=PresentationFramework StackTrace: at System.Windows.Markup.WpfXamlLoader.Load(XamlReader xamlReader, IXamlObjectWriterFactory writerFactory, Boolean skipJournaledProperties, Object rootObject, XamlObjectWriterSettings settings, Uri baseUri) at System.Windows.Markup.WpfXamlLoader.LoadBaml(XamlReader xamlReader, Boolean skipJournaledProperties, Object rootObject, XamlAccessLevel accessLevel, Uri baseUri) at System.Windows.Markup.XamlReader.LoadBaml(Stream stream, ParserContext parserContext, Object parent, Boolean closeStream) at System.Windows.Application.LoadComponent(Object component, Uri resourceLocator) at LabelPrinting.Views.EngineeringViews.StandardEngineeredPrintView.InitializeComponent() in C:\Users\eric_obermuller\source\repos\LabelPrinting\LabelPrinting\Views\EngineeringViews\StandardEngineeredPrintView.xaml:line 1

Inner Exception 1: InvalidOperationException: Operation is not valid while ItemsSource is in use. Access and modify elements with ItemsControl.ItemsSource instead.

Relevant Information

  • I am using MVVM Light.
  • My first view is initially bound to the observable collection and the data is being displayed in the view just fine.
  • Both views use the same data context.
  • The error is thrown when I get the observable collection from the view model.

StandardEngineeredViewModel Revision List

private ObservableCollection<Revision> _ModelRevisionList = new ObservableCollection<Revision>();
public ObservableCollection<Revision> ModelRevisionList
{
    get { return _ModelRevisionList; } //Error thrown here upon get
    set { Set(ref _ModelRevisionList, value); }
}

StandarEngineeredView List Box that is bound

<ListBox
   BorderBrush="{StaticResource BackgroundBlueBrush}" 
   ItemsSource="{Binding ModelRevisionList}" 
   SelectedItem="{Binding SelectedRevision}"
   DisplayMemberPath="Date" 
   Margin="70 10" 
   MinHeight="150"
   MaxHeight="150"
   ItemStringFormat="{}{0:MM/dd/yyyy}"/>

StandardEngineeredPrintView gridview that is bound

<Border Grid.Column="1" MaxHeight="250" MaxWidth="400" MinWidth="400">
    <DataGrid ItemsSource="{Binding ModelRevisionList}" AutoGenerateColumns="False">
        <DataGridTextColumn Header="Date" Binding="{Binding Date}"/>
        <DataGridTextColumn Header="Edited By" Binding="{Binding EditedBy}"/>
        <DataGridTextColumn Header="Description" Binding="{Binding Description}"/>
    </DataGrid>
</Border>

Data Context that is set in both views

DataContext="{Binding StandardEngineeredViewInstance, Source={StaticResource Locator}}"

View Model Locator

 public class ViewModelLocator
{
    /// <summary>
    /// Initializes a new instance of the ViewModelLocator class.
    /// </summary>
    public ViewModelLocator()
    {
        ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
        SetupNavigation();

        if (ViewModelBase.IsInDesignModeStatic)
        {
            // Create design time view services and models
            SimpleIoc.Default.Register<IDataAccessService, DataAccessService>();
        }
        else
        {
            // Create run time view services and models

            SimpleIoc.Default.Register<IDataAccessService, DataAccessService>();
        }
    }

    public StandardEngineeredViewModel StandardEngineeredViewInstance
    {
        get
        {
            SimpleIoc.Default.Register<StandardEngineeredViewModel>();
            return ServiceLocator.Current.GetInstance<StandardEngineeredViewModel>();
        }
    }

    public static void Cleanup()
    {
        // TODO Clear the ViewModels
    }
    private static void SetupNavigation()
    {
        SimpleIoc.Default.Unregister<IFrameNavigationService>();
        var navigationService = new FrameNavigationService();
        navigationService.Configure("StandardEngineeredPrintView", new Uri("/Views/EngineeringViews/StandardEngineeredPrintView.xaml", UriKind.Relative));
        SimpleIoc.Default.Register<IFrameNavigationService>(() => navigationService);
    }
}

Now due to the error, I am thinking it has something to do with the fact that I am using the observable collection in my StandardEngineeredView before navigating to the StandardEngineeredPrintView. Are you able to bind two views to the same data source? Am I doing something wrong that I am just not aware of?

I appreciate any suggestions and if you would like some more information/code just let say so.

Thank you!

c#
wpf
mvvm
binding
mvvm-light
asked on Stack Overflow Aug 30, 2018 by Selthien • edited Aug 30, 2018 by Selthien

1 Answer

0

Okay the solution was really simple. I my datagrid was set up incorrectly. I had to change it to this:

<DataGrid ItemsSource="{Binding ModelRevisionList}" AutoGenerateColumns="False">
     <DataGrid.Columns>
          <DataGridTextColumn Header="Date" Binding="{Binding Date}"/>
          <DataGridTextColumn Header="Edited By" Binding="{Binding EditedBy}"/>
          <DataGridTextColumn Header="Description" Binding="{Binding Description}"/>
     </DataGrid.Columns>
</DataGrid>

Forgot the DataGrid.Columns

answered on Stack Overflow Aug 30, 2018 by Selthien

User contributions licensed under CC BY-SA 3.0