Cannot get a datagrid to show the sample products collection WPF

Jul 3, 2012 at 5:24 PM

Beginning user of WPF and MVVM.

I am walking through the getting started sample doc. I have created a new WPF simpleMVVM project from the proj template.

Grid is not showing the result set when the button is clicked. The model looks to be creating the mockobject collection of products and the notifypropertychange seems to fire...but no display of product row data.

Can someone look at my code and see what I may be missing?

 

ProductListViewModel:

using System;
using System.Windows;
using System.Threading;
using System.Collections.ObjectModel;
using SimpleMvvmToolkit;
using Crowsol.QB.UI.Services;
using Crowsol.QB.UI.Models;
using SimpleMvvmToolkit.ModelExtensions;

namespace Crowsol.QB.UI
{
    /// <summary>
    /// This class contains properties that a View can data bind to.
    /// <para>
    /// Use the <strong>mvvmprop</strong> snippet to add bindable properties to this ViewModel.
    /// </para>
    /// </summary>
    public class ProductsListViewModel : ViewModelBase<ProductsListViewModel>
    {
        #region Initialization and Cleanup

        // TODO: Add a member for IXxxServiceAgent
        private IProductServiceAgent serviceAgent;

        // Default ctor
        public ProductsListViewModel() { }

        // TODO: ctor that accepts IXxxServiceAgent
        public ProductsListViewModel(IProductServiceAgent serviceAgent)
        {
            this.serviceAgent = serviceAgent;
        }

        #endregion

        #region Notifications

        // TODO: Add events to notify the view or obtain data from the view
        public event EventHandler<NotificationEventArgs<Exception>> ErrorNotice;

        #endregion

        #region Properties

        private ObservableCollection<Product> _products;
        public ObservableCollection<Product> Products
        {
            get { return _products; }
            set
            {
                _products = value;
                NotifyPropertyChanged(m => m._products);
            }
        }

        #endregion

        #region Methods

        public void LoadProducts()
        {
            var products = serviceAgent.LoadProducts();
            Products = new ObservableCollection<Product>(products);
        }

        #endregion

        #region Completion Callbacks

        // TODO: Optionally add callback methods for async calls to the service agent
        
        #endregion

        #region Helpers

        // Helper method to notify View of an error
        private void NotifyError(string message, Exception error)
        {
            // Notify view of an error
            Notify(ErrorNotice, new NotificationEventArgs<Exception>(message, error));
        }

        #endregion
    }
}

 

ProductListView.xaml :

<UserControl x:Class="Crowsol.QB.UI.ProductListView"
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
             xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
             mc:Ignorable="d" 
             d:DesignHeight="392" d:DesignWidth="573"
             DataContext="{Binding Source={StaticResource Locator}, Path=ProductListViewModel}"
             >
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="68*" />
            <RowDefinition Height="324*" />
        </Grid.RowDefinitions>
      <Button Content="Load Products" Height="23" HorizontalAlignment="Left" Margin="7,10,0,0" Name="LoadProductsButton" VerticalAlignment="Top" Width="101">
        <!-- Add reference to Microsoft.Expression.Interactions.dll, System.Windows.Interactivity.dll -->
        <!-- Use mvvmxmlns snippet to add i and ei namespace prefixes -->
        <i:Interaction.Triggers>
          <i:EventTrigger EventName="Click">
            <ei:CallMethodAction
                    TargetObject="{Binding}"
                    MethodName="LoadProducts"/>
          </i:EventTrigger>
        </i:Interaction.Triggers>
      </Button>
        <DataGrid AutoGenerateColumns="True"
                  Grid.Row="1"
                  Height="312"
                  Name="dataGrid1"
                  Width="573"
                  ItemsSource="{Binding Path=Products, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                  EnableRowVirtualization="False">
          
        </DataGrid>
    </Grid>
</UserControl>

Jul 3, 2012 at 9:30 PM

Nevermind,

Fixed it.

In the Products property declaration, I had the NotifyPropertyChanged pass a ref to the private property variable as opposed to referencing the Property accessor itself.

// m_products should be m.Products        
private ObservableCollection<Product> _products;
        public ObservableCollection<Product> Products
        {
            get { return _products; }
            set
            {
                _products = value;
                NotifyPropertyChanged(m => m._products);
            }
        }