This project contains two comboboxes, one textbox, one ADO.Net Entity Model (with two tables), and a little less than 50 lines of code (including the using directives) in the MainWindow.xaml.cs file (code behind MainWindow -- VS2012 -- win7 --
source code below). The two tables are named Authors (the master table -- 3 rows) and Books (the detail table -- 6 rows) and the tables are constrained (related) by PK-FK. On project startup Combo1 gets populated by all the rows (3 rows)
from the Authors table and displays the first row (first author ordered asc), and simultaneously combo2 gets populated with the corresponding books (detail) rows for the author being displayed/selected in Combo1, and Combo2 displays the first book (ordered
asc), and the textbox displays the description of the book being displayed in Combo2. If another author is selected in Combo1 then the content of Combo2 changes to the corresponding book(s) for that author, and the book displayed in Combo2 changes to
the first book for the selected author (books also ordered asc), and the description in the textbox changes to the currently selected row in Combo2.
I want to keep the same functionality/operation in this project -- except using the MVVM pattern. I am "guessing" that the model would most likely consist of two observableCollection objects where the first observableCollection object would
contain all the rows in the Authors table, and the 2nd observableCollection object would contain the corresponding row(s) from the Books table. Then I am "guessing" that the viewmodel would contain three properties for populating the two comboboxes
and the textbox.
Where I start losing understanding (of the MVVM pattern) is that I don't quite know the rules when I need to use an ICommand command. Can I achieve the same functionality/operation as the original (non-mvvm) WPF project with just properties
(and the propertyChanged event)? Or will ICommand be required somewhere since there are click actions in the comboboxes? I am hoping someone could clarify the rules here (and set me straight if I am on the right or wrong track thinking about observable
collections in the model ...), and I would be very greatful if someone coul demostrate some code samples for the model and view model for this project (like will I need to implement INotifyPropertyChanged in the model?). Oh, would the xaml have to be
modified also (besides the bindings) to function with MVVM?
First I create the two tables (Authors and Books) in a sql server database (of any choosing on like sql express). Here is the Tsql for that
create table Author (AuthorId int primary key, AuthorName nvarchar(50))
create table Book (BookId int primary key, AuthorId int, Title nvarchar(50), Description nvarchar(200), Price money)
alter table Book add constraint FK_Book_Author foreign key (AuthorId) references Author (AuthorId)
insert into Author values (1, 'Gambardella, Matthew')
insert into Author values (2, 'Ralls, Kim')
insert into Author values (3, 'Corets, Eva')
insert into Book values (1, 1, 'XML Developers Guide', 'An in-depth look at creating applications with XML.', 4.95)
insert into Book values (2, 1, 'Foods of the world.', 'Simply a book about food.', 5.95)
insert into Book values (3, 1, 'Cars', 'A book about cars.', 8.95)
insert into Book values (4, 2, 'Scarecrows', 'This be could horror or agriculture.', 4.15)
insert into Book values (5, 3, 'Book of blue', 'First in a series of books about colors', 6.30)
insert into Book values (6, 3, 'EF', 'Some tips and trics on Entity Frameworks', 3.45)
Then I create a blank WPF project and add an ADO.Net Entity Model which I name Bookshop.edmx (using EF5 -- or EF6 works also). The context I named BookshopEntities, then I select Authors and Books from the Entities Model wizard and save the model as
BookshopModel.
Here is the xaml for MainWindow.xaml
<Window x:Class="myWPF_EFsample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"><Grid><Grid.ColumnDefinitions><ColumnDefinition Width="180" /><ColumnDefinition Width="*" /></Grid.ColumnDefinitions><Grid.RowDefinitions><RowDefinition Height="25" /><RowDefinition Height="*" /></Grid.RowDefinitions><ComboBox DisplayMemberPath="AuthorName" ItemsSource="{Binding}" IsSynchronizedWithCurrentItem="true"
Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="1" Name="cbAuthors" SelectionChanged="cbAuthors_SelectionChanged" /><ComboBox DisplayMemberPath="Title" ItemsSource="{Binding}" IsSynchronizedWithCurrentItem="true"
Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="1" Name="cbBooks" SelectionChanged="cbBooks_SelectionChanged" /><TextBlock Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Name="tbDesc"/></Grid></Window>
and here is the code in MainWindow.xaml.cs (the MainWindow code behind)
using System.Linq;
using System.Windows;
using System.Windows.Controls;
namespace myWPF_EFsample
{
public partial class MainWindow : Window
{
BookshopEntities ctx = new BookshopEntities();
public MainWindow()
{
InitializeComponent();
FillAuthors();
}
private void FillAuthors()
{
var q = (from a in ctx.Authors select a).ToList();
cbAuthors.DataContext = q;
}
private void FillBook()
{
Author author = (Author)cbAuthors.SelectedItem;
var q = (from book in ctx.Books
orderby book.Title
where book.AuthorId == author.AuthorId
select book).ToList();
cbBooks.DataContext = q;
}
private void FillDescription()
{
Book book = (Book)cbBooks.SelectedItem;
tbDesc.Text = book.Description;
}
private void cbAuthors_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
FillBook();
}
private void cbBooks_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
FillDescription();
}
}
}
Any suggestions or examples how to set up the Model and ViewModel would be greatly appreciated -- and if I will need a RelayCommand class.
Rich P