Model: The data access layer.
View: The GUI(Windows, Graphics, controls,..) and the codebehind file) or in other-words a view is a .xaml/.xaml.cs pair.
ViewModel: Can be compared to a Controller, who binds data between the View and the Model. It passes the commands form View to Model.
Our example is a simple data binding of ListBox.
- Create a new WPF project.
- Create three folders to the project- Model,View and ViewModel.
- Delete the MainWindow.xaml from the project, and create a new WPF window in View folder. I named it ListBoxView.( It is a clean practice to postfix views with 'View', view models with 'ViewModel' and Models with 'Model')
- Modify the App.xaml and App.xaml.cs as follows.
<!--App.xaml-->
<Application x:Class="ListBoxSampleNamespace.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Startup="Application_Startup">
<Application.Resources>
</Application.Resources>
</Application>
//App.xaml.cs
public partial class App : Application
{
private void Application_Startup(object sender, StartupEventArgs e)
{
ListBoxView myView = new ListBoxView();
Application.Current.MainWindow = myView;
myView.Show();
}
}
namespace ListBoxSampleNamespace.Model
{
public class PeopleDataModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public PeopleDataModel(string fname, string lname, int age)
{
this.FirstName = fname;
this.LastName = lname;
this.Age = age;
}
}
}
// Interaction logic for ListboxTemplateViewModel
namespace ListBoxSampleNamespace.ViewModel
{
public class ListboxTemplateViewModel
{
public ObservableCollection<PeopleDataModel> PeopleDataCollection { get; set; }
public ListboxTemplateViewModel()
{
public class ListboxTemplateViewModel : INotifyPropertyChanged
{
public ObservableCollection<PeopleDataModel> PeopleDataCollection { get; set; }
public ListboxTemplateViewModel()
{
PeopleDataCollection = new ObservableCollection<PeopleDataModel>();
PeopleDataCollection.Add(new PeopleDataModel("FirstName1", "LastName1", 27));
PeopleDataCollection.Add(new PeopleDataModel("FirstName2", "LastName2", 32));
PeopleDataCollection.Add(new PeopleDataModel("FirstName3", "LastName3", 57));
PeopleDataCollection.Add(new PeopleDataModel("FirstName4", "LastName4", 51));
}
}
}
The ViewModel class has list of PeopleDataModel. ObservableCollection is built-in generic collection used for databinding, it can raises events automatically when an item is added or removed.(Right now we are not raising events in this example).
/// Interaction logic for ListBoxView.xaml
public partial class ListBoxView : Window
{
public ListBoxView()
{
InitializeComponent();
DataContext = new ListBoxSampleNamespace.ViewModel.ListboxTemplateViewModel();
}
}
}
<ListBox x:Name="PeopleListBox" Width="300" MaxHeight="150" ItemsSource="{Binding PeopleDataCollection}" IsSynchronizedWithCurrentItem="True">
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Orange" BorderThickness="2" Background="OrangeRed">
<StackPanel Orientation="Vertical">
<TextBlock FontSize="12" Text="{Binding Path=FirstName}" />
<TextBlock FontSize="12" Text="{Binding Path=LastName}" />
<StackPanel>
<TextBlock FontSize="10" Text="{Binding Path=Age}" />
</StackPanel>
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
The
ItemsSource="{Binding PeopleDataCollection}"
of the ListBox defines the Binding source. Without a DataTemplate, our ListBox currently looks like this:This happens because without specific instructions, the ListBox just calls ToString when trying to display the objects in the PeopleDataCollection.
Therefore, we can overrides the ToString method, then the ListBox displays the string representation of each object in the underlying Collection(PeopleDataCollection).In our example add this code to the PeopleDataModel class.
public override string ToString()
{
string result = null;
result = FirstName +LastName+ Age.ToString();
return result;
}
Still this method is inflexible. Also, if we want to bind to XML data, we cannot override ToString().
Therefore the solution is to define a DataTemplate. Set the ItemTemplate property of the ListBox to a DataTemplate. What we specify in the DataTemplate becomes the visual structure of our data object.
We are giving instructions that each item appears as three TextBlock elements within a StackPanel. Each TextBlock element is bound to a property of the PeopleDataModel class.
When you run this program:
0 comments:
Post a Comment