jump to navigation

Using Type Converters in WPF July 31, 2011

Posted by fofo in C#, c# 3.0, c# 4.0, general .net, Visual Studio 2008, Visual Studio 2010, VS 2010, WPF, XAML.
Tags:
3 comments

In this post I would like to talk/show you how to implement type conversions in WPF.

We must talk a little bit for Binding in WPF before we move on to explain why we use type converters and show a hands on example.

So what is Binding in WPF? In WPF we can bind any property of any object to any other property of some other object.

Binding is typically done in XAML by using the Binding markup extensions.For example

<TextBox Text=”{Binding Path=Property}” />

The syntax above implies that we do not set the value of the Target to some literal value.

When we use binding in XAML , what really happens is that in runtime we create an instance of the Binding class, setting various properties that affect its behaviour.

We can create bindings in code as well. Basically in WPF it is entirely up to the developer if he will write any XAML code to implement the application.

I strongly recommend to use the XAML approach.

In binding we have a Target object/element. In order for binding to be possible, that object/element must inherit from (be an object of type) FrameworkElement.

In the previous small example, TextBox is a Control and inherits from FrameworkElement class. All controls inherit from that class. So all the WPF controls and their properties/attributes can be part of a Binding situation.

Speaking of properties/attibutes the Target property must be a DepenencyProperty. So the “Text” property in the previous example is a Dependency property.

Obviously we need to have some sort of source to bind to.Any .Net object can be a binding source.We can display customers from a customer object in a ListBox control.

We can bind to datasets and entity classes. We can bind to properties of other elements. For example we can bind the value of a Slider control to a TextBlock.

So we can bind from various sources. Basically any CLR object can play the role of the Binding source.

We can specify the mode of how data flows between the data and the source. So we have

  • TwoWay – Data flows both directions
  • OneWay – Data flows only from the source to the target
  • OneTime – Data flows only from the source to the target but we bind only once to the source. It is a useful only if we do not expect the source to change.
  • OneWayToSource – Data flows from the target to the source, for example, we have a textbox that we tell it not to bother read the initial value from the source but update the source with any value the user types in

In order to have a better idea how binding works have a look at the picture below

So where value converters figure in the above scenario? In many cases the binding source is of a type that needs to be converted so that the target property can bind to.

Value converters are instances of classes that implement the IValueConverter interface.

I will create a hands on example to demonstrate how to use type converters in WPF.

1) Launch Visual Studio 2010/2008. From the available templates, choose a WPF application template.Choose an appropriate name for your application. I have named it WpfApplicationConverters. I will use C# as the development language.

2) We will create a simple WPF application , with a button, 2 comboboxes and a border. The first combobox will load with various font families.Every time the user will select a different font from the combobox the FontFamily attribute of the Button element will reflect those changes.

3) The second combobox will load with integer values ( 1-10). Every time the user selects a different value from this combobox then the BorderThickness property of the Border element will change to reflect this change.

In both cases we need to need some sort of value conversions. The values in the FontFamily Combobox are of type String and we need to convert it to FontFamily type.

The values of the second combobox has integer values.These values need to be mapped to another type, the BorderThickness property.The BorderThickness property has four values.

We need to have some sort of classes where we make the conversion.

4) We need to write the UI first. The XAML for the UI follows

<Window x:Class="WpfApplicationConverters.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">

<StackPanel>

<Border BorderBrush="DarkCyan" >

<StackPanel>

<Grid Height="210">

<Button FontSize="16"  Content="I am a button"  Height="34"  Name="button1" Width="164"   Margin="166,41,161,135" />

<ComboBox Height="32" Name="BorderThicknessComboBox" Width="120" Margin="82,128,289,50"   />

<ComboBox Name="FontFamilyComboBox" Width="136" Height="34"  Margin="243,128,112,48"></ComboBox>

</Grid>

</StackPanel>

</Border>

</StackPanel>

</Window>

5) Run your application and make sure it works.

Now I need to populate the comboxoxes with the initial values. I will use the Loaded event of each control.

I will write the code in the MainWindow.xaml.cs file.

using System.Windows;
using System.Linq;
using System.Collections.Generic;

namespace WpfApplicationConverters
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{

InitializeComponent();
}

private void ThicknessComboBoxSetUp()
{
BorderThicknessComboBox.ItemsSource = Enumerable.Range(1, 10);
BorderThicknessComboBox.SelectedIndex = 0;
}

private void FillComboBoxWithFontFamilies()
{

FontFamilyComboBox.ItemsSource = new List<string>() { "Arial", "Arial Black", "Comic Sans MS", "Courier New", "Georgia",
            "Lucida Sans Unicode", "Times New Roman", "Trebuchet MS", "Verdana" };
FontFamilyComboBox.SelectedIndex = 0;
}

private void FontFamilyComboBox_Loaded(object sender, RoutedEventArgs e)
{
FillComboBoxWithFontFamilies();
}

private void BorderThicknessComboBox_Loaded(object sender, RoutedEventArgs e)
{
ThicknessComboBoxSetUp();
}

6) The code above is very easy to follow and understand.I create two methods ThicknessComboBoxSetup() and FillComboBoxWithFontFamilies() and then use these methods in the BorderThicknessComboBox_Loaded and FontFamilyComboBox_Loaded event handling routines.

Obviously you need to change the XAML code as well.


<ComboBox Height="32" Name="BorderThicknessComboBox" Width="120" Margin="82,128,289,50" Loaded="BorderThicknessComboBox_Loaded"/>

<ComboBox Name="FontFamilyComboBox" Width="136" Height="34"  Margin="243,128,112,48" Loaded="FontFamilyComboBox_Loaded" />

7) Run your application and make sure everything works as expected. Now we will implement the type value converters.

Add a new item to the project, a class file. Name it FontFamilyConversions.cs. The code for the class follows

using System.Windows.Media;
using System.Windows.Data;

namespace WpfApplicationConverters
{
class FontFamilyConversions: IValueConverter
{

public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
FontFamily fontfamily = new FontFamily("Verdana");
if (value != null)
{
fontfamily = new FontFamily(value.ToString());
}
return fontfamily;
}

public object ConvertBack(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return null;
}
}
}

8) The code above is easy to understand. I implement the IValueConverter interface and the to methods, Convert and ConvertBack methods.

I actually implement only the Convert method.I convert the string value to a new value of type FontFamily.

9) Add a new class to the project so you can perform the second conversion.Name it IntergerToThicknessConversions.cs

The conversion in this case will be from a type integer to a type Thickness.The code for the class follows


using System;
using System.Windows.Data;
using System.Windows;

namespace WpfApplicationConverters
{
class IntergerToThicknessConversions:IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
Thickness thicknessValue = new Thickness(0);

if (value != null)
{
thicknessValue =
new Thickness(System.Convert.ToInt32(value));
}
return thicknessValue;

}

public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

10) Now we need to hook these classes with the XAML.The first thing I do is to add the namespace of all the classes in our project.

 xmlns:local="clr-namespace:WpfApplicationConverters"

Then I need to define the classes that implement the type conversions. I do that inside a Window.Resources element.

<Window.Resources>
    <local:FontFamilyConversions x:Key="FontFamilyConversions" />
    <local:IntergerToThicknessConversions x:Key="IntergerToThicknessConversions" />
</Window.Resources>

The last thing is to bind the target properties to the Comboboxes selected values and the Conversion classes.  I use markup extensions in XAML. I bind to the appropriate combobox for each case, then set the Path property to the SelectedValue. For the conversions I use the Converter attribute to bind to the appropriate conversion classes.

<Border BorderBrush="DarkCyan"  BorderThickness="{Binding ElementName=BorderThicknessComboBox, 
Path=SelectedValue, Converter={StaticResource IntergerToThicknessConversions}}">

<Button FontSize="16"  Content="I am a button"  Height="34"  Name="button1" Width="164" 
FontFamily="{Binding SelectedValue,ElementName=FontFamilyComboBox, Mode=OneWay,  
 Converter={StaticResource FontFamilyConversions}}" Margin="166,41,161,135" />

The whole code for the UI is this


<Window x:Class="WpfApplicationConverters.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"
xmlns:local="clr-namespace:WpfApplicationConverters"
>
<Window.Resources>
<local:FontFamilyConversions x:Key="FontFamilyConversions" />
<local:IntergerToThicknessConversions x:Key="IntergerToThicknessConversions" />
</Window.Resources>
<StackPanel>

<Border BorderBrush="DarkCyan"  BorderThickness="{Binding ElementName=BorderThicknessComboBox, Path=SelectedValue,
Converter={StaticResource IntergerToThicknessConversions}}">

<StackPanel>

<Grid Height="210">

<Button FontSize="16"  Content="I am a button"  Height="34"  Name="button1" Width="164"  FontFamily="{Binding SelectedValue, ElementName=FontFamilyComboBox, Mode=OneWay, Converter={StaticResource FontFamilyConversions}}" Margin="166,41,161,135" />

<ComboBox Height="32" Name="BorderThicknessComboBox" Width="120" Margin="82,128,289,50"  Loaded="BorderThicknessComboBox_Loaded"  />

<ComboBox Name="FontFamilyComboBox" Width="136" Height="34"  Loaded="FontFamilyComboBox_Loaded" Margin="243,128,112,48"></ComboBox>
</Grid>
</StackPanel>
</Border>
</StackPanel>
</Window></pre>

Run your application and change the Font Family for the button and the Thickness of the border. Make sure everything works as expected.

Email me if you need the source code.
Hope it helps !!!

Advertisements

An introduction to MVVM pattern using WPF July 17, 2011

Posted by fofo in C#, c# 4.0, Visual Studio 2010, WPF.
Tags: , ,
25 comments

In this post I will show you how to build a simple WPF Application using the popular and well know MVVM (Model View View Model) pattern.

I assume that you know the basics of XAML,WPF. I am going to use a hands-one example using Visual Studio and 2010.

Before we go on and begin with our example I must say a few things about MVVM.Make a note that we can use this pattern when building Silverlight applications as well.

So what is MVVM? In a nutshell it is a UI Design Pattern. You do not have to explore too many things or spend too much time studying this pattern before start using it.

A pattern is a documented solution to a specific software problem. So MVVM being a pattern,  is a set of guidelines that makes it much easier to write WPF applications.

It is based on a very important software principle called seperation of concerns.By building WPF applications using MVMV we have solid maintainable code.

By breaking apart our application, enables us to do UI testing.

On top of that we have applications that ( that are built with MVVM ) are much more maintenable and extensible. We keep the designers and the developers happy!!!! Each of them can focus on their tasks and noone interferes with each other’s work.

Let’s have a closer look on the main components of MVVM pattern. Have a look at the picture below.It gives a high level overview of the pattern.

MVVM Pattern

MVVM Pattern

The Model has no reference to the View or the ViewModel . It does not or care about the existence of the View or the Model.

The Model is that data. It could be an xml file or a data access layer (e.g EF). It could be a custom object(s) representing a part of our domain.

The View does not have a reference to the Model. A View is defined in XAML and should not have any logic in the code-behind. It binds to the ViewModel by only using data binding.
The ViewModel can be thought of as an abstraction of the View. It provides enough information about the Model data points that the View can use for data-binding. It contains Commands the View can use to interact with the Model. The ViewModel has a reference to the Model.

Let’s start with our hands on example.I will create a simple WPF application

1) Launch Visual Studio 2010 (any edition will do). Choose C# as the development language and WPF Application from the available templates.

2) Choose a suitable name for your application. I have named it “WpfMVVM”

3) Add 3 folders in your solution with the names View,Model,ViewModel.

4) I will use a custom object to store the data so I will add a new class to the Model folder. I will name it Footballer.cs ( yes, we will save and display footballer names ). I will add some properties on this class like  firstname,lastname,age,height,weight and another little property called SavedTime so I know when the data was last updated. So the first version of the Footballer class follows.

   class Footballer
    {

        private string _firstname;

        public string FirstName
        {
            get { return _firstname; }
            set
            {
                _firstname = value;

            }
        }

        private string _lastname;

        public string LastName
        {
            get { return _lastname; }
            set
            {

                _lastname = value;

            }
        }

        private int _age;

        public int Age
        {
            get { return _age; }
            set
            {
                _age = value;

            }
        }

        private double _height;

        public double Height
        {
            get { return _height; }
            set
            {
                _height = value;

            }
        }

        private double _weight;

        public double Weight
        {
            get { return _weight; }
            set
            {
                _weight = value;

            }
        }

        private DateTime _SavedTime;

        public DateTime SavedTime
        {
            get { return _SavedTime; }
            set
            {
                _SavedTime = value;

            }
        }

}

Then I need to notify my UI (View) that some of these properties changed. I do that by implementing the INotifyPropertyChanged interface.

Now the View is notified when there changes in the property values,since when that happens notifications are fired. This allows the View to display any changes that have been made in the object’s underlying properties. The second version of the Footballer class follows


class Footballer:INotifyPropertyChanged
{

private string _firstname;

public string FirstName
{
get { return _firstname; }
set
{
_firstname = value;
OnPropertyChanged("FirstName");

}
}

private string _lastname;

public string LastName
{
get { return _lastname; }
set
{

_lastname = value;
OnPropertyChanged("LastName");
}
}

private int _age;

public int Age
{
get { return _age; }
set
{
_age = value;
OnPropertyChanged("Age");
}
}

private double _height;

public double Height
{
get { return _height; }
set
{
_height = value;
OnPropertyChanged("Height");
}
}

private double _weight;

public double Weight
{
get { return _weight; }
set
{
_weight = value;
OnPropertyChanged("Weight");
}
}

private DateTime _SavedTime;

public DateTime SavedTime
{
get { return _SavedTime; }
set
{
_SavedTime = value;
OnPropertyChanged("SavedTime");
}
}

public event PropertyChangedEventHandler PropertyChanged;

public void OnPropertyChanged(string property)
{
if (PropertyChanged !=null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}

}

}

If I want to implement data validation logic, the Model class is a good place to do it.In this case I need to implement the IDataErrorInfo interface.In this example I will add some validation for the fields “FirstName”, “Lastname”. These fields cannot be empty.

The third version of the Footballer class follows


class Footballer:INotifyPropertyChanged,IDataErrorInfo
{

private string _firstname;

public string FirstName
{
get { return _firstname; }
set
{
_firstname = value;
OnPropertyChanged("FirstName");

}
}

private string _lastname;

public string LastName
{
get { return _lastname; }
set
{

_lastname = value;
OnPropertyChanged("LastName");
}
}

private int _age;

public int Age
{
get { return _age; }
set
{
_age = value;
OnPropertyChanged("Age");
}
}

private double _height;

public double Height
{
get { return _height; }
set
{
_height = value;
OnPropertyChanged("Height");
}
}

private double _weight;

public double Weight
{
get { return _weight; }
set
{
_weight = value;
OnPropertyChanged("Weight");
}
}

private DateTime _SavedTime;

public DateTime SavedTime
{
get { return _SavedTime; }
set
{
_SavedTime = value;
OnPropertyChanged("SavedTime");
}
}

public event PropertyChangedEventHandler PropertyChanged;

public void OnPropertyChanged(string property)
{
if (PropertyChanged !=null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}

}

public string Error
{
get { return null; }
}

public string this[string columnName]
{
get

{
string theerror = string.Empty;

if ((string.IsNullOrEmpty (_firstname)))
{
theerror = "This field is required";
}

else if ((string.IsNullOrEmpty(_lastname)))
{
theerror = "This field is required";
}
return theerror;
}
}

}

We will have to make some changes to the XAML (Set the ValidatesOnDataErrors=True for firstname and lastname elements) for this to work but I will show you later.

Νow let’s move to the ViewModel implementation. This model must have properties that expose instances of the Model objects.

So in this case we must have a property in the ViewModel class that exposes the Footballer class that lives in the Model.

Add a new item to your project, a class file, name it FootballerViewModel.cs

The first thing I need to do in my new class is to implement the INotifyPropertyChanged interface.This is because the View is bound to the ViewModel. INotifyPropertyChanged interface is the way to push data to the View.

The first version of the ViewModel class follows

class FootballerViewModel:INotifyPropertyChanged
{

public event PropertyChangedEventHandler PropertyChanged;

public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}

}
}

Let’s create a property that  is an instance of the Model object .The second version of the ViewModelclass follows

class FootballerViewModel:INotifyPropertyChanged
{

private Footballer _myfootballer;

public Footballer MyFootballer
{
get { return _myfootballer; }
set

{

_myfootballer = value;
OnPropertyChanged("MyFootballer");

}
}

public event PropertyChangedEventHandler PropertyChanged;

public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}

}
}

Now I will use the constructor for the ViewModel class and populate it with some random data.

The third version of the ViewModel follows


class FootballerViewModel:INotifyPropertyChanged
{

public FootballerViewModel()
{
LoadFootballers();
}

private void LoadFootballers()
{
MyFootballer  = new Footballer()
{
FirstName = "Steven",
LastName = "Gerrard",
Age = 31,
Weight = 88.6,
Height = 1.84

};
}

private Footballer _myfootballer;

public Footballer MyFootballer
{
get { return _myfootballer; }
set

{

_myfootballer = value;
OnPropertyChanged("MyFootballer");

}
}

public event PropertyChangedEventHandler PropertyChanged;

public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}

}
}

Now, let’s create the View. The View will be purely XAML. It consists of the visual elements like buttons,textboxes. It is not responsible for retrieving data,implement business logic or validation logic.

First things first. Move the MainWindow.xaml file to the View folder.

Go to the App.xaml file and change the StartupUri attribute of the Application element to StartupUri=”View/MainWindow.xaml”


<Window x:Class="WpfMVVM.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.RowDefinitions>
<RowDefinition Height="46*" />
<RowDefinition Height="46*" />
<RowDefinition Height="46*" />
<RowDefinition Height="46*" />
<RowDefinition Height="46*" />
<RowDefinition Height="46*" />
<RowDefinition Height="46*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="121*" />
<ColumnDefinition Width="382*" />
</Grid.ColumnDefinitions>
<TextBlock Height="23" HorizontalAlignment="Left" Margin="10,12,0,0" Name="textBlock1" Text="First Name:" VerticalAlignment="Top"
Width="82" FontSize="16" />
<TextBox Grid.Column="1" Height="23" HorizontalAlignment="Left" Margin="45,12,0,0" Name="textBox1" VerticalAlignment="Top"
Width="266" />
<TextBlock Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="12,8,0,0" Name="textBlock2" Text="Last Name:"
VerticalAlignment="Top" Width="82" FontSize="16" />
<TextBlock Grid.Row="2" Height="23" HorizontalAlignment="Left" Margin="12,9,0,0" Name="textBlock3" Text="Age:"
VerticalAlignment="Top" FontSize="16" />
<TextBlock Grid.Row="3" Height="23" HorizontalAlignment="Left" Margin="10,12,0,0" Name="textBlock4" Text="Height:"
VerticalAlignment="Top" FontSize="16" />
<TextBlock Grid.Row="4" Height="23" HorizontalAlignment="Left" Margin="10,9,0,0" Name="textBlock5" Text="Weight:"
VerticalAlignment="Top" FontSize="16" />
<TextBox Grid.Column="1" Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="45,9,0,0" Name="textBox2"
VerticalAlignment="Top" Width="266"  />
<TextBox Grid.Column="1" Grid.Row="2" Height="23" HorizontalAlignment="Left" Margin="45,9,0,0" Name="textBox3"
VerticalAlignment="Top" Width="266"  />
<TextBox Grid.Column="1" Grid.Row="3" Height="23" HorizontalAlignment="Left" Margin="45,12,0,0" Name="textBox4"
VerticalAlignment="Top" Width="266"  />
<TextBox Grid.Column="1" Grid.Row="4" Height="23" HorizontalAlignment="Left" Margin="45,9,0,0" Name="textBox5"
VerticalAlignment="Top" Width="266"  />
<TextBlock Grid.Row="5" HorizontalAlignment="Left" Margin="12,12,0,13" Name="textBlock6" Text="Time Saved:" FontSize="16" />
<TextBox Grid.Column="1" Grid.Row="5" Height="23" HorizontalAlignment="Left" Margin="45,13,0,0" Name="textBox6"
VerticalAlignment="Top" Width="266" />
<Button Content="Update" Grid.Column="1" Grid.Row="6" Height="24" HorizontalAlignment="Left"
Margin="92,15,0,0" Name="button1" VerticalAlignment="Top" Width="156" FontSize="16" FontFamily="Garamond"
FontWeight="Bold" BorderBrush="#FF407F2E" Foreground="#FFE39223" Background="#FF175D17" />
</Grid>
</Window>

Now let’s make the necessary changes on the View so it can bind to the Model through the ViewModel.

We have first to make a reference to theViewModel class/object so I include the following namespace.

xmlns:football="clr-namespace:WpfMVVM.ViewModel"

This is the first step to hook a View to the ViewModel. We tell WPF where our ViewModel lives.

Then I will create the ViewModel as a resource (static resource).

<Window.Resources>

        <football:FootballerViewModel x:Key="FootballerViewModel" />

</Window.Resources>

Then in the Grid element I make the following change

Grid DataContext="{StaticResource FootballerViewModel}" >

The DataContext property inherits its value to child elements. So you can set the DataContext on a layout container (Grid) and its values are inherited to all child elements. This is very useful in our case where we want to bind to the same data object.

Databinding is typically done in XAML by using the {Binding} markup extension. We have to bind the Text attribute of the TextBox element to the various properties as implemented in the Model through the ViewModel.

<TextBox Grid.Column="1" Height="23" HorizontalAlignment="Left" Margin="45,12,0,0" Name="textBox1"
VerticalAlignment="Top" Width="266" Text="{Binding MyFootballer.FirstName ValidatesOnDataErrors=True}" />

<TextBox Grid.Column="1" Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="45,9,0,0" Name="textBox2"
VerticalAlignment="Top" Width="266" Text="{Binding MyFootballer.LastName, ValidatesOnDataErrors=True}" />

<TextBox Grid.Column="1" Grid.Row="2" Height="23" HorizontalAlignment="Left" Margin="45,9,0,0" Name="textBox3"
VerticalAlignment="Top" Width="266" Text="{Binding MyFootballer.Age}" />

<TextBox Grid.Column="1" Grid.Row="3" Height="23" HorizontalAlignment="Left" Margin="45,12,0,0" Name="textBox4"
VerticalAlignment="Top" Width="266" Text="{<strong>Binding MyFootballer.Height</strong>}" />

<TextBox Grid.Column="1" Grid.Row="4" Height="23" HorizontalAlignment="Left" Margin="45,9,0,0" Name="textBox5"
VerticalAlignment="Top" Width="266" Text="{Binding MyFootballer.Weight}" />

<TextBox Grid.Column="1" Grid.Row="5" Height="23" HorizontalAlignment="Left" Margin="45,13,0,0" Name="textBox6"
VerticalAlignment="Top" Width="266" Text="{Binding MyFootballer.SavedTime}" />

Run your application and see the values from the domain object appearing in the textboxes.

We do have a button in our UI. We need to update data from the UI and bind the new data to the textboxes.

We need to have a different communnication between the View and the ViewModel. In this case we will use Commands.

First we need to update the XAML.

<Button Content="Update" Grid.Column="1" Grid.Row="6" Height="24" HorizontalAlignment="Left" Margin="92,15,0,0"
Name="button1" VerticalAlignment="Top" Width="156" FontSize="16" FontFamily="Garamond"
FontWeight="Bold" BorderBrush="#FF407F2E" Foreground="#FFE39223" Background="#FF175D17"
Command="{Binding SaveFootballerCommand}" />

So I updated the XAML for the button element by adding the Command=”{Binding SaveFootballerCommand}”

Now we must add some more code in our ViewModel.

public class SaveFootballerCommand:ICommand
{

Action _saveMethod;

public bool CanExecute(object parameter)
{
return true;
}

public event EventHandler CanExecuteChanged;

public void Execute(object parameter)
{
_saveMethod.Invoke();
}
}

I create a new class, SaveFootballerCommand, that has to implement the ICommand interface. Then I define an Action, _saveMethod, which is what is executed when the button is clicked.

The CanExecute tells me if I am allowed to execute the command.Then I create the Execute method and invoke it.

Now we need to create a property in my ViewModel that exposes that command.

private ICommand _SaveFootballerCommand;

public ICommand SaveFootballerCommand
{
get { return _SaveFootballerCommand; }
set
{
_SaveFootballerCommand = value;
OnPropertyChanged("SaveFootballerCommand");

}
}

Now we need to create an instance of the SaveFootballerCommand.

private void FireCommand()
{
SaveFootballerCommand = new SaveFootballerCommand(updateFootballer) ;
}

I place the inside my constructor the FireCommand() method.

public FootballerViewModel()
{
FireCommand();
LoadFootballers();
}

The updateFootballer method is going to be invoked when the command is executed.So I must implement it.

private void updateFootballer()
{

MyFootballer.SavedTime = DateTime.Now;

}

Now I need to create a constructor of the SavePersonCommand class that takes a parameter. The code follows

public SaveFootballerCommand(Action updateFootballer)
{
_saveMethod = updateFootballer;

}

The whole code for the ViewModel class follows

public SaveFootballerCommand(Action updateFootballer)
{
class FootballerViewModel:INotifyPropertyChanged
{

public FootballerViewModel()
{
FireCommand();
LoadFootballers();
}

private void FireCommand()
{
SaveFootballerCommand = new SaveFootballerCommand(updateFootballer) ;
}

private void updateFootballer()
{

MyFootballer.SavedTime = DateTime.Now;

}

private void LoadFootballers()
{
MyFootballer  = new Footballer()
{
FirstName = "Steven",
LastName = "Gerrard",
Age = 31,
Weight = 88.6,
Height = 1.84

};
}

private Footballer _myfootballer;

public Footballer MyFootballer
{
get { return _myfootballer; }
set

{

_myfootballer = value;
OnPropertyChanged("MyFootballer");

}
}

private ICommand _SaveFootballerCommand;

public ICommand SaveFootballerCommand
{
get { return _SaveFootballerCommand; }
set
{
_SaveFootballerCommand = value;
OnPropertyChanged("SaveFootballerCommand");

}
}

public event PropertyChangedEventHandler PropertyChanged;

public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}

}
}

}

Run your application and click the button.Note how the date is updated.

Note that we do not have written a single line of code to the MainWindow.xaml.cs file.

Now that we have a clear understanding of what MVVM is and what the different components are, let’s review again the main concepts.

The ViewModel is responsible for the state and behaviour of the View and it acts like the “middle man” between the View and the Model.

It the middle layer and its main job is to send View information to the Model and Model information to the View.

It has no dependency on the View so we can reuse the ViewModel on different Views or even other platforms.

The ViewModel exposes the Model as properties or commands.

In any case it must implement the INotifyPropertyChanged interface.

The View binds to properties in the ViewModel. It does that by setting the DataContext of a View to an instance of the ViewModel object.

The Model is tha data.Simple as that. The Model’s job is to represent the data and has no knowledge of where or how the data will be presented.

By using this pattern we can have the designers in our company designing the Views with xaml using Visual Studio Designer or Blend. The developers in our company can work with the Model and the ViewModel writing the data access code and businnes logic . We reduce the development time.

This is great pattern because we can make our code more testable and maintainable.

If you want to have a look at the MVVM more closely have a look here.

It would be nice if you could spare some time and have a  look at these related patterns with MVVM pattern like MVP,MVC,PM.

Hope it helps!!! Email me if you need the source code.

ASP.NET 4.0 Entity DataSource and GridView September 27, 2009

Posted by fofo in ASP.NET 4.0, c# 4.0, Visual Studio 2010.
Tags: , , , ,
3 comments

Recently I had the time to examine thoroughly my blog stats. From that it was evident people liked a lot the posts regarding the new features in .Net 4.0. So in this post I am going to discuss the new Entity DataSource web server control which is  similar to the LINQ to SQL DataSource, except it allows you to use your Entity Framework data object model instead. I will also demonstrates the new features of the GridView control. I have talked about EF and how to build an application with EF and C# in one of my previous posts. In this post I will talk more about the Entity Datasource object and enhancements made in the GridView control.

I will create a sample website as always so it is easier for you to understand.In order to follow along you must have installed in your PC VS 2010 and the .NET 4.0 framework.Obviously we are going to need a data store for our application. I will use the AdventureWorksLt which you can download from this site .

1) Launch Visual Studio 2010 and create a new web site.

2) Choose Asp.Net application from the available templates and C# as the development language

3) You now have your files in the Solution Explorer window.

4) Choose the default.aspx page and go to your Toolbox and under the Data Controls drag and drop an Entity Datasource control on the page.

5) Now you need an Entity Data model that the Entity Datasource can bind to. In the Solution Explorer add (right-click) a new special folder , App_Code

6) Select the App_Code and add a new item(right-click) , ADO.NET Entity Data Model.Leave the default name.

7) In the next window select “Generate from database” and click Necxt.

8) In the next window of the Entity model wizard create a new connection to you database (AdventureWorksLT)or select an existing connection that points to the same db.

9) Save the entity connection settings in the web.config file

10) Click Next on the wizard window. From all the available db objects we want to include in our model only tables and more specifically only the Products table.

11) Select the table and click Finish. So now we have a Product Entity with all the mappings to the database.

12) Select the Entity Datasource control and click the arrow on the right-top corner and select Configure Data Source.

13) Select in the Named Connection option of the wizard and select the AdventureWorkLTEntities and click Next

14) In the EntitySetName select Product and from the available Entity values select ProductID,Name,ListPrice,Size,Weightand and click Finish.

15) Drag and drop on the default.aspx page a Gridview control (control in your Toolbox data controls area).Give it some formatting from the AutoFormat options

16) Set the datasource of the Gridview control to the Entity datasource.

17) Enable Sorting,Paging and Selection for the Gridview control

18) Run your application by hitting F5 from your keyboard. If everything is ok you will be able to see a list of products in your page.

The imporevement in the GridView control is about selecting rows.If you selected an item in GridView(the third one for example) and then browsed through the pages the third item in every page will also be selected. That was not always what we wanted. The GridView control did that based on an index it had and used to find the third item on that page.

We can overcome that by enabling the EnablePersistenSelection property and setting it to True.

Then we need to select the DataKeynames property and set it to ProductID.

19) Now if run our application again and select a product in the first page(6th product), and browse through the pages the product in position 6(index 6) is not selected anymore.Now the selection is made over the underlying primary key and not the index in the view of the GridViewControl

Hope it helps!!!

If you need the source code just email me or just comment on this post.

Add to FacebookAdd to NewsvineAdd to DiggAdd to Del.icio.usAdd to StumbleuponAdd to RedditAdd to BlinklistAdd to TwitterAdd to TechnoratiAdd to Furl

ASP.NET 4.0 and ClientID Mode September 20, 2009

Posted by fofo in ASP.NET 4.0, C#, c# 4.0, Visual Studio 2010.
Tags: ,
1 comment so far

In this post I will be continuing my series of posts regarding ASP.NET 4.0 enhancements.It is now possible to set the name of your controls ClientID attribute, thanks to the ClientIDMode property. Developers requested a better way of setting names of the web server controls and with the new version of ASP.NET 4.0, this is now a reality.

We can demonstrate this with a new project.I will be using C# and VS 2010.

1) Launch Visual Studio 2010

2) Create a new website, select ASP.NET Web site from the available templates. Save your website by giving it an appropriate name. e.g Clientid

3) Create a master page and add it to the page.Leave the default name.

4) Create a new web user control.Leave the default name.

5) In the WebUserControl.ascx add two web server controls,a label control and a textbox control

6) Add the web user control to the asp.net page by typing in the directives section(top of the page)

<%@ Register src=”WebUserControl.ascx” tagname=”WebUserControl1″
tagprefix=”uc1″ %>

7) Run your application. When the default.aspx page is render by the browser, go to View->Source and you will see something like this:

<div>

<span id=”WebUserControl11_Label1″>what is your name?</span>
<input name=”WebUserControl11$TextBox1″ type=”text” id=”WebUserControl11_TextBox1″ />

</div>

This is how the controls take their name. The first part is the name of the parent control and the second part is the name of the control itself. If you have many nested elements you end up with messy control names.If you wanted to access these controls in external Javascript files, you had no other alternative but to use these names.

8) Switch to the WebUserControl.ascx file in VS 2010, and change the ids of the label and textbox control. For example

<asp:Label ID=”namelabel”
<asp:TextBox ID=”txtlabel”

9) Then we set the ClientIDMode to static for both controls. Save your work and run the application

10) When the default.aspx page is render by the browser, go to View->Source and you will see something like this:

<span id=”namelabel”>what is your name?</span>
<input name=”WebUserControl11$txtlabel” type=”text” id=”txtlabel” />

It is evident that now we have the ID values that we want , and it much easier and handy to use.

The other values for the ClientIDMode are:

  • Legacy: This is equivalent to the ClientID property behavior for earlier versions of ASP.NET. This is also the default value.
  • Predictable:This is used in data controls that use repeating templates. It uses ID attributes of the parent control’s naming containers, but generated IDs do not have names that contain strings like “ctlxxx”.
  • Inherit: This specifies that a control’s ID generation is the same as its parent.

Add to FacebookAdd to NewsvineAdd to DiggAdd to Del.icio.usAdd to StumbleuponAdd to RedditAdd to BlinklistAdd to TwitterAdd to TechnoratiAdd to Furl