Microsoft Silverlight 4.0 supports Printing with the help of Printing API. The article will basically deals with step by step approach in achieving Print functionality with MVVM pattern.
- Start Visual Web Developer 2010 Express and create a Silverlight Application
- Select Silverlight 4 from Silverlight version dropdown and click Ok
- Create three folders, Model, ViewModel and Command.
- Right click on Model folder and create a class for model. Let name it as Employee.
and add the following properties
1: public class Employee
2: {
3: /// <summary>
4: /// Gets or sets Employee Id.
5: /// </summary>
6: public int Id { get; set; }
7:
8: /// <summary>
9: /// Gets or sets Employee's First name.
10: /// </summary>
11: public String FirstName { get; set; }
12:
13: /// <summary>
14: /// Gets or sets Employee's Last name.
15: /// </summary>
16: public String LastName { get; set; }
17:
18: /// <summary>
19: /// Gets or sets Location of Employee.
20: /// </summary>
21: public String Location { get; set; }
22:
23: /// <summary>
24: /// Gets Employee's full name.
25: /// </summary>
26: public String FullName { get { return FirstName + " " + LastName; } }
27:
28: /// <summary>
29: /// Returns a collection of dummy details
30: /// </summary>
31: /// <returns>Collection of Employee</returns>
32: public static Collection<Employee> GetEmployeeDetails()
33: {
34: Collection<Employee> empList = new Collection<Employee>()
35: {
36: new Employee() { Id=001, FirstName = "Amanda",
37: LastName = "Hartshorn", Location="United States" },
38: new Employee() { Id=002, FirstName = "Binu",
39: LastName = "Babu", Location="India" },
40: new Employee() { Id=003, FirstName = "Nihas",
41: LastName = "Alangaden", Location="India" },
42: new Employee() { Id=004, FirstName = "Parvathi",
43: LastName = "Mahesh", Location="United States" },
44: new Employee() { Id=005, FirstName = "Tony",
45: LastName = "Xavier", Location="India" }
46: };
47:
48: return empList;
49: }
50: }
- Right click on ViewModel folder in the Silverlight project create a BaseViewModel class
and implement INotifyPropertyChanged interface as shown below
1: public class BaseViewModel : INotifyPropertyChanged
2: {
3: /// <summary>
4: /// This event occurs when a property value changes
5: /// </summary>
6: public event PropertyChangedEventHandler PropertyChanged;
7:
8: protected void OnPropertyChanged(string name)
9: {
10: if (PropertyChanged!= null)
11: {
12: PropertyChanged(this, new PropertyChangedEventArgs(name));
13: }
14: }
15: }
- Create MainPageViewModel class inside ViewModel folder and Command class inside Command folder.
- Implement ICommand interface in Command class as shown below
1: public class Command : ICommand
2: {
3: private bool m_canExecuteCache;
4: private Action<object> m_executeAction;
5: private Func<object, bool> m_canExecute;
6:
7: /// <summary>
8: /// This event occurs when changes occur that
9: /// affect whether the command should execute.
10: /// </summary>
11: public event EventHandler CanExecuteChanged;
12:
13: /// <summary>
14: /// Initializes a new instance of <see cref="Command"/> class.
15: /// </summary>
16: /// <param name="canExecute">
17: /// Encapsulates a method that has one
18: /// parameter and returns a value of the type bool.
19: /// </param>
20: /// <param name="executeAction">
21: /// Encapsulates a method that takes a single
22: /// parameter and does not return a value.
23: /// </param>
24: public Command(Func<object, bool> canExecute, Action<object> executeAction)
25: {
26: m_canExecute = canExecute;
27: m_executeAction = executeAction;
28: }
29:
30: /// <summary>
31: /// This method determines whether the
32: /// command can execute in its current state.
33: /// </summary>
34: /// <param name="parameter">
35: /// Data used by the command. If the command does not
36: /// require data to be passed, this object can be set to null.
37: /// </param>
38: /// <returns>
39: /// true if this command can be executed; otherwise, false.
40: /// </returns>
41: public bool CanExecute(object parameter)
42: {
43: bool enable = m_canExecute(parameter);
44:
45: if (m_canExecuteCache != enable)
46: {
47: m_canExecuteCache = enable;
48:
49: if (CanExecuteChanged != null)
50: {
51: CanExecuteChanged(this, new EventArgs());
52: }
53: }
54:
55: return m_canExecuteCache;
56: }
57:
58: /// <summary>
59: /// This method will be called when the command is invoked.
60: /// </summary>
61: /// <param name="parameter">
62: /// Data used by the command. If the command does not
63: /// require data to be passed, this object can be set to null.
64: /// </param>
65: public void Execute(object parameter)
66: {
67: m_executeAction(parameter);
68: }
69: }
- Create a property for Print Command and another one for Employees collection in the view model. Create an instance of Command and pass the methods which handles can execute and print.
1: public class MainPageViewModel : BaseViewModel
2: {
3: /// <summary>
4: /// Initializes a new instance of <see cref="MainPageViewModel"/> class.
5: /// </summary>
6: public MainPageViewModel()
7: {
8: //Gets dummy data from model
9: Employees = Employee.GetEmployeeDetails();
10: //Setting the Command to the property
11: PrintCommand = new Command.Command(CanPrint, Print);
12: }
13:
14: /// <summary>
15: /// Gets or sets a collection of Employee.
16: /// </summary>
17: public Collection<Employee> Employees { get; private set; }
18:
19: /// <summary>
20: /// Gets or sets the Print Command.
21: /// </summary>
22: public ICommand PrintCommand { get; private set; }
23:
24: #region Private Methods
25:
26: /// <summary>
27: /// Method which is called when the command is invoked.
28: /// </summary>
29: /// <param name="obj">Data used for Printing</param>
30: private void Print(object obj)
31: {
32: //Creates a new instance of the System.Windows.Printing.PrintDocument class.
33: PrintDocument document = new PrintDocument();
34:
35: //Event handler which fires when each page is printing.
36: document.PrintPage += (s, arg) => { arg.PageVisual = obj as UIElement; };
37:
38: // Starts the printing process for the specified
39: // document by opening the print dialog box.
40: document.Print("Print");
41: }
42:
43: /// <summary>
44: /// Method which determines whether the
45: /// command can execute in its current state.
46: /// </summary>
47: /// <param name="obj">Data used for Printing</param>
48: /// <returns>true if the command can be executed; otherwise, false</returns>
49: private bool CanPrint(object obj)
50: {
51: return true;
52: }
53:
54: #endregion
55: }
- Build the Solution and import ViewModel namespace in MainPage.xaml as shown below
1: xmlns:vm="clr-namespace:PrintApplication.ViewModel"
Set the DataContext of the MainPage usercontrol.
1: <UserControl.DataContext>
2: <vm:MainPageViewModel />
3: </UserControl.DataContext>
- Add reference to System.Windows.Controls.Data.dll to the Silverlight project and
import System.Windows.Controls.Data as shown below for adding DataGrid Control to list the Employee details.
1: xmlns:data="clr-namespace:System.Windows.Controls; assembly=System.Windows.Controls.Data"
- Add a TextBlock for displaying Title, DataGrid for displaying the Employees Collection and a button for handling Print action in MainPage.xaml.
1: <UserControl x:Class="PrintApplication.MainPage"
2: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4: xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
5: xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
6: xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"
7: xmlns:vm="clr-namespace:PrintApplication.ViewModel" mc:Ignorable="d">
8: <UserControl.DataContext>
9: <vm:MainPageViewModel />
10: </UserControl.DataContext>
11: <Grid x:Name="LayoutRoot" Background="White" Height="270">
12: <Grid.RowDefinitions>
13: <RowDefinition Height="50" />
14: <RowDefinition />
15: <RowDefinition Height="50" />
16: </Grid.RowDefinitions>
17: <TextBlock x:Name="trbBlock" Text="Printing API Sample" FontSize="18"
18: Margin="3,10,3,14" HorizontalAlignment="Center" Height="26" />
19: <StackPanel x:Name="DisplayPanel" Grid.Row="1" HorizontalAlignment="Center">
20: <data:DataGrid ItemsSource="{Binding Path=Employees}"
21: AutoGenerateColumns="False">
22: <data:DataGrid.Columns>
23: <data:DataGridTextColumn Header="Id" Width="50"
24: Binding="{Binding Id}" />
25: <data:DataGridTextColumn Header="First Name" Width="100"
26: Binding="{Binding FirstName}" />
27: <data:DataGridTextColumn Header="Last Name" Width="100"
28: Binding="{Binding LastName}" />
29: <data:DataGridTextColumn Header="Location" Width="100"
30: Binding="{Binding Location}" />
31: </data:DataGrid.Columns>
32: </data:DataGrid>
33: </StackPanel>
34: <Button Content="Print" Grid.Row="2" Width="100" Height="30"
35: Command="{Binding PrintCommand}"
36: CommandParameter="{Binding ElementName=DisplayPanel}" />
37: </Grid>
38: </UserControl>
- Run the solution and click the Print button to get the Print dialog box.
Thanks
Bimal
No comments:
Post a Comment