(X) Hide this
    • Login
    • Join
      • Say No Bots Generate New Image
        By clicking 'Register' you accept the terms of use .

Data Driven Applications with MVVM Part I: The Basics

(30 votes)
Zoltan Arvai
>
Zoltan Arvai
Joined Jul 20, 2009
Articles:   7
Comments:   5
More Articles
18 comments   /   posted on Jun 15, 2010

This article is compatible with the latest version of Silverlight.

Introduction

In this short series of articles I’ll cover what MVVM is and how to use it in practice, how to solve issues when applying this pattern and how to take advantage from it.

What is MVVM and why you need it

Do you know the feeling, when you start to develop an application, and in the first couple of days you feel good because you made a really good progress? Do you know the feeling, when after a couple of days, you feel that your design is not that best and when you have to modify a little code, you are afraid of the effect it might have on other parts of you code? The first sign of a bad design is when applying a hack is easier than to implement it the proper way. At the end of the week you already have spaghetti code. You have logic that is not testable, it is very tightly coupled with the UI. You cannot make just “minor” changes without taking risks. If someone wants to understand your code, it takes days or weeks to figure out how it works.

This is where MVVM comes into play. MVVM stands for the Model – View – ViewModel pattern. It’s originated from MVC and is specific to WPF and Silverlight. The three most important things that MVVM can offer you:

  1. Testable code
  2. UI is loosely coupled with related logic
  3. Maintainable code

Basic concepts in MVVM

MVVM_pattern_diagram[1]

The Layers:

1.  The View

The View is your User Interface. It’s basically xaml. The view does not interact directly with the model. It does not contain any kind of non-UI related logic. Be aware, don’t be fooled by demo codes and presentations. Sometimes you also have C# code in your code-behind, not just xaml. Sometimes you just cannot get around it. Don’t feel bad about it. There is nothing wrong writing UI related code in the view’s code-behind, after all it’s probably view specific. However sometimes you can write or find workarounds for these cases, in form of Behaviors and Triggers.

2. The Model

The Model can contain entities, DTOs, data source and proxy objects, repositories. It largely depends on what kind of application you are writing. For example if you have a WCF service on the server (above the service layer you may have many other layers, like Business Logic Layer and Data Access Layer, etc.) you will need client side objects to interact with the services. You will need DataContracts (you can transfer data with these objects) and proxy objects to invoke operations. These can be part of your model. I like to refer to the model as the entry point to the rest of the application. The Model and the View DOES NOT know each other, they do not communicate directly.

3. The ViewModel

The ViewModel’s responsibility is to get the necessary data from the model and expose it for the view. Through the view, the user can enter data and trigger actions (commands), so the ViewModel has to interpret this input and the commands, and invoke the appropriate operations on the model and also pass the necessary data.

Interaction between the Layers:

The ViewModel communicates with the Model through an interface. (It’s highly recommended to use interfaces instead of actual implementation). The Model should not know the ViewModel. We try to keep the dependencies low and avoid tightly coupled scenarios.
The communication between the View and the ViewModel is where it gets more interesting. Thanks to the brilliant binding mechanism in Silverlight and WPF the view can get and pass data to and from the ViewModel without actually referencing it.
For example if you have a list of products in the ViewModel and the ViewModel itself is the DataContext of your View, a ListBox defined in your view can DataBind to those product entities. So the Binding mechanism provides this kind of flexibility in this specific pattern.

Let’s see it in action!

MVVM in practice

Well, if you decide to use the MVVM pattern, you’ll see that there are many things that needs to be implemented over and over again. So after a while you may want to develop you own MVVM assisting framework / library to help you along with forthcoming projects. Luckily enough, there are very good solutions out there. The two most famous ones are the MVVM Light Toolkit by Laurent Bugnion, and the Composite Application Library (aka Prism) by the Patterns and Practices Team of Microsoft. However both products are very popular and support MVVM, their main concepts are pretty different. While the MVVM Light Toolkit focuses solely on the MVVM architecture, the Composite Application Library’s main focus is on supporting composite scenarios. Prism supports building Modular applications and also happens to support the MVP architecture. (MVP is like MVVM, but in MVP, the Presenter (ViewModel in our terms) may interact with the View through a well-defined interface directly)) So in our example we will use the MVVM Light Toolkit. (also available, for WPF 3.5, 4.0, Silverlight 3.0, 4.0 and WP7) You can download it from here.

Our demo application will load Books in a ListBox. The selected product’s details will be displayed in a details panel. Also we’ll have remove buttons, so when we click on one, the selected product will be deleted.

So I’m just going to create a simple Silverlight 4.0 project. (Please note, that if you install the MVVM Light Toolkit, you’ll also get Visual Studio Project templates. I’m just going to use the dlls here only)

mvvmstructure

As you can see I’ve created separate folders for my ViewModels and my Views. I have a Master View this is the BooksView UserControl, and a details view, the BookDetailsView UserControl. Also I’ve created a separate Model Project, let’s see that first.

1. The Model Project

Book.cs – This is an entity class, that represents a Book object. It’s very simple does not contain any special code:

 namespace MVVMProductsDemo.Model
 {
    public class Book
    {
        public int BookID { get; set; }
        public string Title { get; set; }
        public string Author { get; set; }
        public decimal Price { get; set; }
    }
 }

IBookDataSource.cs – This is an interface that specifies how the ViewModel will interact with the Model.

 namespace MVVMProductsDemo.Model
 {
     public interface IBookDataSource
     {
         void LoadBooks();
         void RemoveBook(int bookID);
  
         event EventHandler<BooksLoadedEventArgs> LoadBooksCompleted;
         event EventHandler<OperationEventArgs> RemoveBookCompleted;
     }
 }

As you can see, the interface implies that access to the DataSource will be asynchronous. Well, in Silverlight, mostly this is the case. I have two operations. One to load books, and another one to remove a book. I get notified of the results of the operations by events. Below there is an example of the BooksLoadedEventArgs

 namespace MVVMProductsDemo.Model
 {
     public class BooksLoadedEventArgs : OperationEventArgs
     {
         public IEnumerable<Book> Books { get; set; }
  
         public BooksLoadedEventArgs(IEnumerable<Book> books)
         {
            this.Books = books;
         }
     }
 }

Now all I have to do is to actually implement the interface and provide a DataSource implementation. Well for this article a mock (fake) data source is perfect. Not to mention that I plan to use that for testing as well!

 namespace MVVMProductsDemo.Model
 {
     public class MockBookDataSource : IBookDataSource
     {
         List<Book> bookList = new List<Book>();
 
         public MockBookDataSource()
         {
            bookList.Add(
                 new Book
                 {
                     BookID = 1,
                     Author = "Tom Clancy",
                     Title = "Rainbow Six",
                     Price = 29.99m
                 });
   
            bookList.Add(
                 new Book
                 {
                     BookID = 2,
                     Author = "Tom Clancy",
                     Title = "Executive Orders",
                     Price = 19.99m
                 });
   
            bookList.Add(
                 new Book
                 {
                     BookID = 3,
                     Author = "John Grisham",
                     Title = "The Partner",
                     Price = 22.99m
                 });
         }
   
         #region IBookDataSource Members
   
         public void LoadBooks()
         {
             if (LoadBooksCompleted != null)
             {
                 LoadBooksCompleted(this, new BooksLoadedEventArgs(bookList));
             }
         }
   
         public void RemoveBook(int bookID)
         {
             Book bookToDelete = bookList.Single(p => p.BookID == bookID);
             bookList.Remove(bookToDelete);
  
             if (RemoveBookCompleted != null)
                 RemoveBookCompleted(this, new OperationEventArgs());
       }
   
        public event EventHandler<BooksLoadedEventArgs> LoadBooksCompleted;
  
        public event EventHandler<OperationEventArgs> RemoveBookCompleted;
 
        #endregion
     }
 }

As you can see I load some fake books and provide an implementation for LoadBooks and RemoveBook.

2. The ViewModels

ViewModelBase and Property Change Notifications

Let’s get back to the ViewModels. So I have to provide a special model class for my view to display products, load products and handle item selection. This is the BooksViewModel class. The BooksViewModel inherits from ViewModelBase defined in the MVVM Light Toolkit. For data binding to work properly, we need property change notification. ViewModelBase implements the INotifyPropertyChanged interface and provides a protected RaisePropertyChanged method, that we can use to propagate property change notification towards the UI.

Books Collection

The BooksViewModel class exposes a Books property of type ObservableCollection<BookDetailsViewModel>. This property serves as the ItemSource of the ListBox. But why not ObservableCollection<Book>? The answer is simple, I have three reasons:

  1. I want to bind to details panel’s (BookDetailsView) DataContext to the SelectedItem of the ListBox. But if I have Books in the ListBox instead of BookDetailsViewModel instances I cannot do this simply since the DataContext should be a BookDetailsViewModel, not a Book instance.
  2. In the ListBox I might want to define a DataTemplate. In the template I might want to add a button that corresponds to an action defined in the BookDetailsViewModel.
  3. I really want to keep the dependency of the book object very low in my ViewModels. Who knows, maybe I will have to replace it.
 private ObservableCollection<BookDetailsViewModel> books;
  
 public ObservableCollection<BookDetailsViewModel> Books
 
     get { return books; }
     set
     {
         books = value;
         RaisePropertyChanged("Books");
     }
 }

Selected Book

Also I have a SelectedBook property of type BookDetailsViewModel. I’m planning to bind the ListBox’s SelectedItem to this property and also the BookDetailsView’s DataContext should be read from this property. Why not use direct UI to UI binding? I have many reasons:

  1. Most of the time different parts of my application is likely to react if a selected item changes. Not just the UI, other components as well.
  2. I' want to modify the selected book from code as well. The UI needs to reflect those changes!
  3. The designer might screw this one up :)
  4. etc…

So basically I need control over the SelectedItem, in this case the SelectedBook. This is why I’m going to do a two-way binding for the ListBox’s SelectedItem and a one-way binding for the BookDetailsView’s DataContext.

 private BookDetailsViewModel selectedBook;
  
 public BookDetailsViewModel SelectedBook
 {
     get { return selectedBook; }
     set
     {
         selectedBook = value;
        RaisePropertyChanged("SelectedBook");
     }
 }

Loading Books

I can access the DataSource through IBookDataSource, an instance that I get through the BooksViewModel constructor. The DataSource is event-based so I just have to subscribe the the loaded event.

 IBookDataSource bookDataSource;
  
 public BooksViewModel(IBookDataSource bookDataSource)
 {
     this.bookDataSource = bookDataSource;
  
     if (bookDataSource != null)
    {
         bookDataSource.LoadBooksCompleted += new EventHandler<BooksLoadedEventArgs>(bookDataSource_LoadBooksCompleted);
     }
 }

I also create a LoadBooks() method that loads the books from the DataSource;

 public void LoadBooks()
 {
     bookDataSource.LoadBooks();
 }
  
   
 void bookDataSource_LoadBooksCompleted(object sender, BooksLoadedEventArgs e)
 {
     if (e.Error != null)
     {
         //Do dg.
         return;
     }
   
     List<BookDetailsViewModel> loadedBooks = new List<BookDetailsViewModel>();
     foreach (var book in e.Books)
     {
         loadedBooks.Add(new BookDetailsViewModel(book));
     }
   
     Books = new ObservableCollection<BookDetailsViewModel>(loadedBooks);
 }

As you can see after we check a possible error, we refresh the Books Collection. Transformation in necessary into ViewModels since the EventArgs returns IEnumerable<Book> list.

One final step for this View Model. When the user clicks the load button, the ViewModel should get the books. Now we are not binding a simple data property to a simple dependency property like a TextBox.TextProperty. Now we are binding an event to an operation. Of course this is just not possible, we need an extra object, what is called a command. Different MVVM libraries use different names for these commands, like DelegateCommand, ActionCommands or RelayCommands. All of them implement the ICommand interface and this is what matters here. We have RelayCommands in the toolkit. You can bind commands as properties. So all I have to do is to expose a LoadBooksCommand

 private RelayCommand loadBooksCommand;
  
 public RelayCommand LoadBooksCommand
 {
     get
    {
         return loadBooksCommand;
     }
 }
   
 //This line goes to the contructor
 loadBooksCommand = new RelayCommand(LoadBooks);

What did we here? We specified that if a LoadBooksCommand gets invoked than we should call the LoadBooks() method! The buttons have a Command property which is a dependency property. We can directly bind that property to this LoadBooksCommand. Also note, that the second parameter the the RelayCommand’s contstructor is another delegate. Here you can enter a function that checks whether the command in question can actually be executed. If not, then the associated control’s IsEnabled property is set to false. (And this is why I don’t like it. Once more we tie the hands of the designer)

BookDetailsViewModel

The last ViewModel in our case is just a representation of the Book class for now. But that’ll change later!

 namespace MVVMProductsDemo.ViewModels
 {
     public class BookDetailsViewModel : ViewModelBase
     {
         Book book;
  
         public BookDetailsViewModel(Book book)
         {
             this.book = book;
         }
   
         public string Title
         {
             get
             {
                 return book.Title;
             }
             set
             {
                 book.Title = value;
                 RaisePropertyChanged("Title");
             }
         }
   
         public string Author
         {
             get
             {
                 return book.Author;
             }
             set
             {
                 book.Author = value;
                 RaisePropertyChanged("Author");
             }
   
         }
         public decimal Price
         {
             get
             {
                 return book.Price;
             }
             set
             {
                 book.Price = value;
                 RaisePropertyChanged("Price");
             }
         }
   
     }
 }

There we go. We’re done. Remember that I wrote always things like, the user does this or that, that we have a ListBox, and details etc… I never said anything about a concrete UI or layout. Let’s create it now!

3. The Views

Let’s start with the details view. How do we display one item.

details

So this is what we want to create and bind. Here is the code:

 <UserControl x:Class="MVVMProductsDemo.Views.BookDetailsView"
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
     mc:Ignorable="d"
     d:DesignHeight="300" d:DesignWidth="400">
     
     <Grid x:Name="LayoutRoot" Background="White">
         <Grid.RowDefinitions>
             <RowDefinition Height="0.117*"/>
             <RowDefinition Height="0.107*"/>
             <RowDefinition Height="0.117*"/>
             <RowDefinition Height="0.66*"/>
         </Grid.RowDefinitions>
         <Grid.ColumnDefinitions>
             <ColumnDefinition Width="0.345*"/>
             <ColumnDefinition Width="0.655*"/>
         </Grid.ColumnDefinitions>
         <TextBlock Margin="10,0,0,0" TextWrapping="Wrap" d:LayoutOverrides="Width, Height" HorizontalAlignment="Left" VerticalAlignment="Center" Text="Title:"/>
         <TextBlock Margin="10,0,0,0" TextWrapping="Wrap" Grid.Row="1" d:LayoutOverrides="Width, Height" HorizontalAlignment="Left" VerticalAlignment="Center" Text="Author:"/>
         <TextBlock Margin="10,0,0,0" TextWrapping="Wrap" Grid.Row="2" d:LayoutOverrides="Width, Height" HorizontalAlignment="Left" VerticalAlignment="Center" Text="Price:"/>
         <TextBox Grid.Column="1" TextWrapping="Wrap" d:LayoutOverrides="Height" VerticalAlignment="Center" Margin="15,0" Text="{Binding Title, Mode=TwoWay}"/>
         <TextBox Grid.Column="1" TextWrapping="Wrap" Grid.Row="1" d:LayoutOverrides="Height" VerticalAlignment="Center" Margin="15,0" Text="{Binding Author, Mode=TwoWay}"/>
         <TextBox Grid.Column="1" TextWrapping="Wrap" Grid.Row="2" d:LayoutOverrides="Height" VerticalAlignment="Center" Margin="15,0" Text="{Binding Price, Mode=TwoWay}"/>
   
     </Grid>
 </UserControl>
As you can see we did simple two-way bindings like {Binding Title, Mode=TwoWay}.

The BooksView UserControl is where it gets interesting:

master And here is the xaml:

 <ListBox x:Name="lboxBooks" HorizontalAlignment="Left" Margin="8,8,0,29" Width="129" ItemsSource="{Binding Books}" 
          SelectedItem="{Binding SelectedBook, Mode=TwoWay}" DisplayMemberPath="Title"/>
 <Button Command="{Binding LoadBooksCommand}" x:Name="btnLoad" Content="Load Books" HorizontalAlignment="Left" 
         Margin="8,0,0,3" VerticalAlignment="Bottom" Width="129"/>
 <local:BookDetailsView x:Name="bookDetails" Margin="154,8,8,29" DataContext="{Binding SelectedBook}"/>

So we have a ListBox with and ItemsSource bound to the Books property, and the SelectedItem bound two-way to the SelectedBook property. Right now we are not using any DataTemplates yet, this is why the DisplayMemberPath is set to Title (not Book.Title, its BookDetailsViewMode.Title!!!)

The Button has the Command property bound to the LoadBooksCommand so when the user clicks it, it gets invoked. And finally a complete view (a user control) is placed here, this is the BookDetailsView. It’s DataContext is bound to the SelectedBook. So whenever that property changes, the Details will reflect the changes.

4. Wiring Up

Okay so we have the Views and ViewModels but we lack the wire up at the beginning? I told you I don’t want to reference the ViewModel from View. (If you do, that’s not a big problem, many MVVM implementation does that.) But I prefer to do this one more level above, in the application class:

 private void Application_Startup(object sender, StartupEventArgs e)
 {
     BooksView view = new BooksView();
     IBookDataSource dataSource = new MockBookDataSource();
     BooksViewModel viewModel = new BooksViewModel(dataSource);
    view.DataContext = viewModel;
     this.RootVisual = view;
 }

As you can see, this is the place where I specify the actual implementation details for the IBookDatasource. This is the place where I could change it to a live data source. And here is the wire up. I specify the DataContext of the BookView as a BooksViewModel instance. That’s it.

If we run the application now, it just works!

Summary

Okay, what do we have so far? We have a Maintainable, Testable and pretty loosely coupled solution. Also we can easily create different views, for the same data and functionality!

Where do we go from here? We need advanced functionalities, like Removing or Updating an item, we need to battle the problems we face, when implementing these additions, like notifying other views / ViewModels if something changes. We need to create unit tests to make sure, changes in the code does not ruin the application. We need to change to a live data source from the mock one, and of course, we need validation support both on the server and the client!

Well, if you’re interested, read Part 2!

Download the source code


Subscribe

Comments

  • ppopadiyn

    RE: Data Driven Applications with MVVM Part I: The Basics


    posted by ppopadiyn on Jun 15, 2010 16:25

    Quite simple and at the same time accurate explanation of the MVVM basics !!! I would suggest just one improvement in your code, it is in the model. I see that you've created a BooksLoadedEventArgs, if you need to load, let's say Customers, you have to create another EventArgs, e.g: CustomersLoadedEventArgs. In this case you can replace both of the custom EventArgs with one generic class. For example, something like this:

    public class EntityResultEventArgs<T> : OperationEventArgs
    {
        public EntityResultEventArgs( IEnumerable<T> result )
        {
            this.Result = result;
        }

        public IEnumerable<T> Result
        {
            get;
            protected set;
        }
    }

    Otherwise the rest of the code is absolutely the same as I would do it. I am looking forward for the rest of the articles.
    Best Regards

  • -_-

    RE: Data Driven Applications with MVVM Part I: The Basics


    posted by zoltan.arvai on Jun 15, 2010 18:10

    Hi!

    I totally agree with you. Your suggestion makes this more effective and most of the time that is what I do myself (mostly due to the lack of time :) ) However in this article I tried to follow the design guidelines present in the .NET Framework. To make it somewhat more readable.

    There are two more articles, already sent to the silverlightshow guys. Timing is up to them :) The article was intended to be only a single one, however as I wrote it, it was growing pretty fast :) Now I'm thinking on a 4th part :) There is still much to show :)

  • -_-

    RE: Data Driven Applications with MVVM Part I: The Basics


    posted by Mattias on Jun 16, 2010 16:39
    Thanks this is great stuff.
  • -_-

    RE: Data Driven Applications with MVVM Part I: The Basics


    posted by Nabeel on Jul 28, 2010 19:26

    Hi Zoltan,

    I am new to Wpf and Silverlight. I am porting your solution to wpf and I can't seem to figure out the equivalent of line 7

    this.RootVisual = view;

    in the ApplicationStartup event. I have tried something like this

     var mainwindow = new MainWindow();
      this.MainWindow.DataContext = view;
      this.MainWindow.Show();

     But when the MainWindow get displayed its all empty? Any idea?

    Regards,
    Nabeel

  • -_-

    RE: Data Driven Applications with MVVM Part I: The Basics


    posted by Rafael on Jul 31, 2010 06:30

    Great article, simple and to the point.

     Thanks!

  • -_-

    RE: Data Driven Applications with MVVM Part I: The Basics


    posted by zoltan.arvai on Jul 31, 2010 12:17

    Nabeel:

    In your code you write:  

    var mainwindow = new MainWindow(); (here you have a mainwindow variable)
      this.MainWindow.DataContext = view; (here you set this.MainWindows which is at this point is not the previously created instance... plus you set the datacontext to view... what is view? that should be a viewmodel...
      this.MainWindow.Show();

    This should be something like this:

                var mainwindow = new MainWindow();
                this.MainWindow = mainwindow;
                this.MainWindow.DataContext = viewModel;
                this.MainWindow.Show();
  • -_-

    RE: Data Driven Applications with MVVM Part I: The Basics


    posted by Sunit on Aug 23, 2010 05:26
    Is the full project contained in the rar files? I can't see anything other than the Mvmm dlls and App files?
  • -_-

    RE: Data Driven Applications with MVVM Part I: The Basics


    posted by zoltan.arvai on Aug 23, 2010 10:05
    The full solution is supposed to be there... and I just double checked it, and the solution is there. (I used winrar)
  • -_-

    RE: Data Driven Applications with MVVM Part I: The Basics


    posted by Sunit Joshi on Aug 23, 2010 20:41

    If you don't mind, can you please post a zip of the same?

    thanks

    Sunit

  • -_-

    RE: Data Driven Applications with MVVM Part I: The Basics


    posted by Surf-O-Matic on Aug 26, 2010 19:06

    Thank you very much for this article !!

    Things are getting very clear for me now .

  • -_-

    RE: Data Driven Applications with MVVM Part I: The Basics


    posted by Shailesh on May 18, 2011 23:24

    Can you upload the source code zip as well?

    Nice article

  • MauricioLeyzaola

    Re: Data Driven Applications with MVVM Part I: The Basics


    posted by MauricioLeyzaola on Aug 29, 2011 04:27

    Thank you Zoltan, very good explanation. I have been with my fingers freezed for weeks without knowing where to start this big WPF project. At least know I have a path.

    Let's move on with the next chapter.

  • ImranAli

    Re: Data Driven Applications with MVVM Part I: The Basics


    posted by ImranAli on Sep 16, 2011 07:52
    This is not good for huge ERP type system.If some one follow MVVM sure he will depress and stop coding.
  • Karthik

    Re: Data Driven Applications with MVVM Part I: The Basics


    posted by Karthik on Feb 19, 2012 23:54

    Hi,

    I am new to Silverlight. Really good article.

    I have a question. 

    I see "OperationEventArgs" being used. Is this part of MVVM tool kit or am i missing any assembly?

    namespace MVVMProductsDemo.Model
     {
         public class BooksLoadedEventArgs : OperationEventArgs
         {
             public IEnumerable<Book> Books { get; set; }
      
             public BooksLoadedEventArgs(IEnumerable<Book> books)
             {
                this.Books = books;
             }
         }
     }
  • Karthik

    Re: Data Driven Applications with MVVM Part I: The Basics


    posted by Karthik on Feb 20, 2012 02:18

    Hi,

    I am new to Silverlight. Really good article.

    I have a question. 

    I see "OperationEventArgs" being used. Is this part of MVVM tool kit or am i missing any assembly?

    namespace MVVMProductsDemo.Model
     {
         public class BooksLoadedEventArgs : OperationEventArgs
         {
             public IEnumerable<Book> Books { get; set; }
      
             public BooksLoadedEventArgs(IEnumerable<Book> books)
             {
                this.Books = books;
             }
         }
     }
  • haiyun592

    Re: Data Driven Applications with MVVM Part I: The Basics


    posted by haiyun592 on Apr 25, 2012 15:57
    Where is the OperationEventArgs come from?
  • ShohelShipon

    Re: Data Driven Applications with MVVM Part I: The Basics


    posted by ShohelShipon on May 14, 2012 05:36

    Greate article boss.

    Thanks a lot.

  • harrykod

    Re: Data Driven Applications with MVVM Part I: The Basics


    posted by harrykod on May 16, 2012 22:26
    I am using ADO.Net Entity Framework in the Model Folder. Do i have to create an interface for each entity in my ADO.Net Entity Model?

Add Comment

Login to comment:
  *      *       

From this series