views:

81

answers:

2

Hi, I'm writing an application in WPF, using the MVVm toolkit and have problems with hooking up the viewmodel and view.

The model is created with ado.net entity framework.

The viewmodel:

public class CustomerViewModel
    {
        private Models.Customer customer;
        //constructor
        private ObservableCollection<Models.Customer> _customer = new ObservableCollection<Models.Customer>();
        public ObservableCollection<Models.Customer> AllCustomers
        {
            get { return _customer; }

        }
        private Models.Customer _selectedItem;
        public Models.Customer SelectedItem
        {
            get { return _selectedItem; }

        }
        public void LoadCustomers()
        {
            List<Models.Customer> list = DataAccessLayer.getcustomers();
            foreach (Models.Customer customer in list)
            {
                this._customer.Add(customer);
            }
            }
        }

And the view (no code behind at the moment):

<UserControl x:Class="Customers.Customer"
             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" 
             mc:Ignorable="d" 
             xmlns:vm ="clr-namespace:Customers.ViewModels"
             d:DesignHeight="300" d:DesignWidth="300"
             xmlns:toolkit="http://schemas.microsoft.com/wpf/2008/toolkit" >

    <Grid>
        <toolkit:DataGrid ItemsSource="{Binding AllCustomers}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" AutoGenerateColumns="True">

        </toolkit:DataGrid>

        <toolkit:DataGrid ItemsSource="{Binding SelectedItem.Orders}">

        </toolkit:DataGrid>



    </Grid>
</UserControl>

And dataaccesslayer class:

 class DataAccessLayer
    {
        public List<Customer> customers = new List<Customer>();

        public static List<Customer> getcustomers()
        {
            entities db = new entities();

            var customers = from c in db.Customer.Include("Orders")
                           select c;
            return customers.ToList();
        }


    }

The problem is that no data is displayed simply because the data context is not set. I tried to do it in a code-behind but is did not work. I would prefer to do it in a xaml file anyway. Another problem is with the SelectedItem binding - the code is never used.

Thanks for help! Regards, EV.

+1  A: 

Is this what you're looking for?

Chris Nicol
yes and no. I need to somehow call the method getcustomers(). Should I do it in a viewmodel constructor? Doesn't seem very good.
EVA
Personally I would have the ViewModel call getcustomers() in the constructor. What do you feel is not good about it? When the view renders it will create a new instance of the ViewModel and at that point you want the data to be retrieved, so it makes sense for the constructor to do it.
Chris Nicol
What about the xaml construction <UserControl.DataContext> in Resources?
EVA
The only major issue with declaring the object in the XAML is that any error thrown during the VM construction, will be eaten by a XAML parsing error. We have switched off to using a DI like MEF to have inject the VM into the View's DataContext at Load. OnLoad can fire multiple times so make sure you short circuit it with an _isLoaded field or something of the like.
Agies
Yes that's a better solution to use DI for sure. Nice comment!
Chris Nicol
A: 

Since this is using the MVVM paradigm, I would instance your ViewModel in the constructor for the View. My View/ViewModels typically follow this sequence of events:

  1. View is instanced
  2. View constructor instances ViewModel
  3. ViewModel initializes
  4. ViewModel runs data getting procedures(separate thread)
  5. ViewModel calls OnPropertyChanged("") to alert View that something has changed; check everything

My ViewModel is instanced from the XAML codebehind (sorry this is in VB.NET, have not gotten around to learning C# well enough to trust myself with it):

Public Sub New()
    MyBase.New()
    Me.DataContext = New EditShipmentViewModel(Me) 'pass the view in to set as a View variable
    Me.InitializeComponent()
End Sub

Initially I hoped to have something like

<UserControl>
    <UserControl.DataContext>
        <Local:EditShipmentViewModel>
    </UserControl.DataContext>
</UserControl>

But that did not work out like I wanted it to.

Hope that helps a little.

OffApps Cory