PRN212Lab - 01 - ProductManagement - UsingLINQ and WPF
PRN212Lab - 01 - ProductManagement - UsingLINQ and WPF
1. Introduction
Imagine you're an employee of a store named ProductStore. Your manager has asked you to
develop a WPF application for product management. The application has to support adding,
viewing, modifying, and removing products—a standardized usage action verbs better known as
Create, Read, Update, Delete (CRUD).
This lab explores creating an application using WPF with .NET Core, and C#. An "in-memory
database" will be created to persist the car's data, so a collection is called List will be used for
reading and managing product data.
2. Lab Objectives
In this lab, you will:
Use the Visual Studio.NET to create WPF application and Class Library (.dll) project.
Use the Visual Studio.NET to create Windows Forms and Class Library (.dll) project.
Create a List of persisting products using LINQ to Object to find items.
Apply passing data in WPF application
Apply Repository pattern in a project.
Add CRUD action methods to WPF application.
Run the project and test the WPF application actions.
1|Page
Activity 01: Build a solution by Visual Studio.NET
Create a Blank Solution named ProductManagementDemo then add new a Class Library
project named BusinessObjects, DataAccessObjects, Repositories, Services and a WPF
project named ProductManagement
Note:
Data Source in this case is the “In memory Database” (using List collection)
Services Project – This project represents a layer or component responsible for
implementing the business logic of an application.
Repository Project – This project provides an abstraction layer between the
application’s business logic and the underlying data source.
Data Access Layer Project – This project used to abstract and encapsulate the logic for
accessing data from a data source, such as a database.
2|Page
3|Page
Activity 02: Write codes for the BusinessObjects project
Step 01. On the BusinessObjects project, add a class named Product.cs and write codes as
follows:
using System.Collections.Generic;
namespace BusinessObjects {
25 references
public partial class Category {
O references
public Category()
{
Products = new HashSet<Product>(); }
8 references
public Category (int catID, string catName)
{
this.CategoryId = catID;
this.CategoryName = catName;
}
1 reference
public int CategoryId { get; set; }
1 reference
public string CategoryName { get; set; }
1 reference
public virtual ICollection<Product> Products { get; set; }
}
}
Step 02. On the BusinessObjects project, add a class named Category.cs and write codes as
follows:
namespace BusinessObjects {
46 references
public partial class Product {
6 references
public Product(int id, string name, int catId, short unitInStock, decimal price) {
this.ProductId= id;
this.ProductName = name;
this.CategoryId= catId;
this. UnitsInStock = unitInStock;
this. UnitPrice = price;
}
12 references
public int ProductId { get; set; }
7 references
public string ProductName { get; set; }
4|Page
7 references
public int? CategoryId { get; set; }
7 references
public short? UnitsInStock { get; set; }
7 references
public decimal? UnitPrice { get; set; }
O references
public virtual Category Category { get; set; }
}
}
Step 02. On the BusinessObjects project, add a class named Category.cs and write codes as
follows:
namespace BusinessObjects
{
8 references
public partial class Account Member {
1 reference
public string MemberId { get; set; } = null!;
2 references
public string MemberPassword { get; set; } = null!;
O references
public string FullName { get; set; } = null!;
O references
public string? EmailAddress { get; set; }
2 references
public int? MemberRole { get; set; }
}
}
|
Step 01. On the DataAccessLayer project, add a class named CategoryDAO.cs and write codes
as follows:
using System.Collections.Generic; using BusinessObjects;
namespace DataAccessLayer
{
1 reference
public class Category DAO
{
1 reference
public static List<Category> GetCategories()
{
Category beverages = new Category (1, "Beverages");
5|Page
Category condiments = new Category (2, "Condiments");
Category confections = new Category (3, "Confections"); Category dairy new Category (4,
"Dairy Products");
Category grains new Category (5, "Grains/Cereals");
Category meat new Category (6, "Meat/Poultry");
Category produce new Category (7, "Produce");
Category seafood new Category (8, "Seafood");
var listCategories = new List<Category>();
try
{
listCategories.Add(beverages);
listCategories.Add(condiments);
listCategories.Add(confections);
listCategories.Add(dairy);
listCategories.Add(grains);
listCategories.Add(meat);
listCategories.Add(produce);
listCategories.Add(seafood);
}
catch (Exception e)
{
throw new Exception(e.Message);
}
return listCategories;
}
}
}
Step 02. On the DataAccessLayer project, add a class named ProductDAO.cs and write codes
as follows:
using System.Collections.Generic;
using System.Linq;
using BusinessObjects;
namespace DataAccessLayer
{
3 references
public class ProductDAO
{
private static List<Product> listProducts;
1 reference
public ProductDAO()
{
Product chai new Product(1, "Chai", 3, 12, 18);
Product chang new Product (2, "Chang", 1, 23, 19);
Product aniseed new Product(3, "Aniseed Syrup", 2, 23, 10);
listProducts = new List<Product> { chai, chang, aniseed };
//Product chef new Product(4, "Chef Anton's Cajun Seasoning", 2, 34, 22);
6|Page
//Product chefMix new Product (5, "Chef Anton's Gumbo Mix", 2, 45, 34); //Product grandma
new Product (6, "Grandma's Boysenberry Spread", 2, 21, 25);
//Product uncle = new Product(7, "Uncle Bob's Organic Dried Pears", 7, 22, 30);
//Product northwoods = new Product (8, "Northwoods Cranberry Sauce", 2, 10, 40);
//Product mishi new Product(9, "Mishi Kobe Niku", 6, 12, 97);
//Product ikura new Product (10, "Ikura", 8, 13 , 32);
// listProducts = new List<Product> { chai, chang, aniseed, chef, chefMix, grandme
}
1 reference
public List<Product> GetProducts()
{
return listProducts;
}
7|Page
}
8|Page
Step 01. On the Repositories project, add an interface named ICatergoryRepository.cs and
write codes as follows:
using System.Collections.Generic; using BusinessObjects;
namespace Repositories {
2 references
public interface ICategory Repository {
2 references
List<Category> GetCategories();
}
}
Step 02. On the Repositories project, add an interface named IProductRepository.cs and write
codes as follows:
Vusing System.Collections.Generic; using BusinessObjects;
namespace Repositories
{
2 references
public interface IProductRepository
{
2 references
void SaveProduct (Product p);
2 references
void Delete Product (Product p); 2 references
void Update Product (Product p);
2 references
List<Product> GetProducts();
2 references
Product GetProductById(int id);
}
}
Step 03. On the Repositories project, add an interface named IAccountRepository.cs and write
codes as follows:
using BusinessObjects;
namespace Repositories
{
2 references
public interface IAccountRepository {
2 references
AccountMember GetAccountById(string accountID);
9|Page
}
}
using System.Collections.Generic;
using BusinessObjects;
using DataAccessLayer;
namespace Repositories
{
1 reference
public class Category Repository: ICategoryRepository
{
2 references
public List<Category> GetCategories() => Category DAO.GetCategories();
}
}
Vusing BusinessObjects;
using System.Collections.Generic;
using DataAccessLayer;
namespace Repositories
{
1 reference
public class ProductRepository: IProductRepository
{
2 references
public void DeleteProduct (Product p) => ProductDAO.DeleteProduct(p);
2 references
public void SaveProduct (Product p) => ProductDAO.SaveProduct(p);
2 references
public void UpdateProduct (Product p) => ProductDAO. UpdateProduct(p);
2 references
public List<Product> GetProducts() => ProductDAO.GetProducts();
2 references
public Product GetProductById(int id)=>ProductDAO.GetProductById(id);
}
}
using BusinessObjects;
using DataAccessLayer;
namespace Repositories
{
1 reference
public class AccountRepository: IAccountRepository
{
2 references
public Account Member GetAccountById(string accountID)
=>AccountDAO.GetAccountById(accountID);
}
10 | P a g e
}
Step 01. On the Services project, add an interface named ICatergoryService.cs and write codes
as follows:
using BusinessObjects;
using System.Collections.Generic; {
namespace Services
2 references
public interface ICategoryService
{
2 references
List<Category> GetCategories();
}
}
Step 02. On the Services project, add an interface named IProductService.cs and write codes as
follows:
using BusinessObjects;
using System.Collections.Generic; namespace Services {
2 references
public interface IProductService {
2 references
void SaveProduct (Product p);
2 references
void DeleteProduct (Product p);
2 references
void UpdateProduct (Product p);
2 references
List<Product> GetProducts();
2 references
Product GetProductById(int id);
}
}
Step 03. On the Services project, add an interface named IAccountService.cs and write codes as
follows:
using BusinessObjects;
namespace Services
{
2 references
11 | P a g e
public interface IAccountService
{
2 references
AccountMember GetAccountById(string accountID);
}
}
using BusinessObjects;
using Repositories;
using System.Collections.Generic;
namespace Services
{
2 references
public class ProductService: IProductService
{
private readonly IProductRepository iProductRepository;
1 reference
public ProductService()
{
}
iProductRepository = new ProductRepository();
2 references
public void DeleteProduct (Product p)
{
iProductRepository. DeleteProduct(p);
}
2 references
public Product GetProductById(int id)
{ return iProductRepository.GetProductById(id);
}
2 references
public List<Product> GetProducts()
{
12 | P a g e
}
return iProductRepository.GetProducts();
2 references
public void SaveProduct (Product p)
{
iProductRepository. Save Product(p);
}
2 references
public void UpdateProduct (Product p)
{
}
iProductRepository. UpdateProduct(p);
}
}
using BusinessObjects;
using Repositories;
namespace Services
{
2 references
public class AccountService: IAccountService
{
private readonly IAccountRepository iAccountRepository;
1 reference
public AccountService() {
iAccountRepository = new AccountRepository();
}
2 references
public AccountMember GetAccountById(string accountID)
{
}
return iAccountRepository.GetAccountById(accountID);
}
}
لم
13 | P a g e
Activity 04: Design UI and write codes for WPF project
14 | P a g e
Step 01. On the WPF project, design UI as follows:
<Window x:Class="WPFApp.MainWindow"
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"
xmlns:local="clr-namespace:WPFApp"
mc:Ignorable="d"
Loaded="Window_Loaded"
WindowStartupLocation="CenterScreen"
15 | P a g e
Title="Product Management" Height="670" Width="710">
<Grid>
<Grid>
<Grid.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<GradientStop Color="#0099FF" Offset="0"/>
<GradientStop Color="#FF347BDA" Offset="0.794"/>
<GradientStop Color="#FF60B1E7" Offset="1"/>
<GradientStop Color="#FF596FDD" Offset="0.309"/>
<GradientStop Color="#FF472FDE" Offset="0.484"/>
</LinearGradientBrush>
</Grid.Background>
<Grid.RowDefinitions>
<RowDefinition Height="60"/>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
<RowDefinition Height="*"/>
<RowDefinition Height="30"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="119.415"/>
<ColumnDefinition Width="30.585"/>
<ColumnDefinition Width="47*"/>
<ColumnDefinition Width="513*"/>
</Grid.ColumnDefinitions>
16 | P a g e
<Label x:Name="label4" Margin ="2,2,2,2" Content="Category" Grid.Column="0" Grid.Row="5"
Grid.ColumnSpan="2"/>
<ComboBox x:Name="cboCategory" Margin ="4,4,4,4" Grid.Column="2" Grid.Row="5"
Grid.ColumnSpan="2" />
</Grid>
</Grid>
</Window>
<Window x:Class="WPFApp.LoginWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
17 | P a g e
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"
xmlns:local="clr-namespace:WPFApp"
mc:Ignorable="d"
Title="LoginWindow" Height="450" Width="800"
WindowStartupLocation="CenterScreen"
WindowStyle="None"
Background="Transparent"
AllowsTransparency="True">
<Grid>
<Border CornerRadius="10"
BorderThickness="2"
Opacity="0.95">
<Border.BorderBrush>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<GradientStop Color="#0099FF" Offset="0"/>
<GradientStop Color="#DA34AE" Offset="0.75"/>
<GradientStop Color="#FF60B1E7" Offset="1"/>
<GradientStop Color="#FF596FDD" Offset="0.309"/>
<GradientStop Color="#FF8C57CA" Offset="0.484"/>
</LinearGradientBrush>
</Border.BorderBrush>
<Border.Background>
<LinearGradientBrush StartPoint="0,1" EndPoint="1,0">
<GradientStop Color="#060531" Offset="0"/>
<GradientStop Color="#FF472FDE" Offset="1"/>
</LinearGradientBrush>
</Border.Background>
<Grid>
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Center"
Height="82" VerticalAlignment="Top" Width="632">
<TextBlock Text="LOGIN WINDOW"
Foreground="White"
FontSize="28"
FontWeight="Medium"
FontFamily="Montserrat"
Cursor="Hand"
Margin="180,30,0,0" Width="377"
/>
</StackPanel>
<StackPanel
Orientation="Vertical"
Margin="82,102,82,68">
<TextBlock Text="Username"
Foreground="DarkGray"
FontSize="12"
FontWeight="Medium"
FontFamily="Montserrat"
Margin="0,35,0,0"/>
<TextBox x:Name="txtUser"
18 | P a g e
FontSize="13"
FontWeight="Medium"
FontFamily="Montserrat"
Foreground="White"
CaretBrush="LightGray"
BorderBrush="DarkGray"
BorderThickness="0,0,0,2"
Height="28"
VerticalContentAlignment="Center"
Margin="0,5,0,0"
>
<TextBox.Background>
<LinearGradientBrush></LinearGradientBrush>
</TextBox.Background>
</TextBox>
<TextBlock Text="Password"
Foreground="DarkGray"
FontSize="12"
FontWeight="Medium"
FontFamily="Montserrat"
Margin="0,15,0,0"/>
<PasswordBox x:Name="txtPass"
FontSize="13"
FontWeight="Medium"
FontFamily="Montserrat"
Foreground="White"
CaretBrush="LightGray"
BorderBrush="DarkGray"
BorderThickness="0,0,0,2"
Height="28"
VerticalContentAlignment="Center"
Margin="0,5,0,0">
<PasswordBox.Background>
<LinearGradientBrush></LinearGradientBrush>
</PasswordBox.Background>
</PasswordBox>
<Button x:Name="btnLogin"
BorderThickness="0"
Content="LOG IN"
Foreground="White"
FontSize="12"
FontFamily="Montserrat"
Cursor="Hand"
Margin="0,50,0,0"
Click="btnLogin_Click">
<Button.Style>
<Style TargetType="Button">
<Setter Property="Background" Value="#0099FF"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#28AEED"/>
</Trigger>
19 | P a g e
</Style.Triggers>
</Style>
</Button.Style>
<Button.Template>
<ControlTemplate TargetType="Button">
<Border Width="150" Height="40"
CornerRadius="20"
Background="{TemplateBinding Background}">
<ContentPresenter VerticalAlignment="Center"
HorizontalAlignment="Center"/>
</Border>
</ControlTemplate>
</Button.Template>
</Button>
</StackPanel>
<StackPanel>
<Button x:Name="btnCancel"
BorderThickness="0"
Content="CANCEL"
Foreground="White"
FontSize="12"
FontFamily="Montserrat"
Cursor="Hand"
Margin="20,350,20,0"
Click="btnCancel_Click">
<Button.Style>
<Style TargetType="Button">
<Setter Property="Background" Value="LightSeaGreen"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="SeaGreen"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
<Button.Template>
<ControlTemplate TargetType="Button">
<Border Width="150" Height="40"
CornerRadius="20"
Background="{TemplateBinding Background}">
<ContentPresenter VerticalAlignment="Center"
HorizontalAlignment="Center"/>
</Border>
</ControlTemplate>
</Button.Template>
</Button>
20 | P a g e
</StackPanel>
</Grid>
</Border>
</Grid>
</Window>
using Services;
using System.Windows;
namespace WPFApp
{
/// <summary> Interaction logic for LoginWindow.xaml
2 references
public partial class LoginWindow: Window
{
private readonly IAccountService iAccount Service;
O references
public LoginWindow()
{
InitializeComponent();
iAccountService = new AccountService();
}
1 reference
private void btnLogin_Click(object sender, RoutedEventArgs e)...
1 reference
private void btnCancel_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
}
}
21 | P a g e
else
{
MessageBox.Show("You are not permission!");
}
}
public MainWindow()
{
InitializeComponent();
iProductService = new ProductService();
iCategory Service = new CategoryService();
}
1 reference
public void LoadCategoryList()
{
try
{
var catList = iCategoryService.GetCategories();
22 | P a g e
cboCategory. Items Source = catList;
cboCategory. DisplayMemberPath = "CategoryName";
cboCategory. SelectedValuePath = "CategoryId";
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error on load list of categories");
}
23 | P a g e
DataGridCell RowColumn =
dataGrid.Columns[0].GetCellContent(row). Parent as DataGridCell;
string id= ((TextBlock)RowColumn.Content).Text;
Product product iProductService.GetProductById(Int32.Parse(id)); txtProductID.Text =
product. ProductId.ToString();
txtProductName.Text = product. ProductName;
txtPrice.Text = product. UnitPrice.ToString();
txtUnitsInStock.Text = product. UnitsInStock.ToString();
cboCategory. SelectedValue = product.CategoryId;
}
1 reference
private void btnClose_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
24 | P a g e
iProductService. DeleteProduct (product);
}
else
{
MessageBox.Show("You must select a Product !");
}
}
catch (Exception ex)
{
}
finally
{
LoadProductList();
using BusinessObjects;
private void resetInput()
{
txtProductID.Text = "";
txtProductName.Text = "";
txtPrice.Text = "";
txtUnitsInStock.Text = "";
cboCategory. SelectedValue = 0;
}
}
25 | P a g e
Step 06. Open App.xaml and then update XAML code as follows:
<Application x:Class="WPFApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WPFApp"
StartupUri="LoginWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>
Activity 05: Run the WPFApp project and test all actions
26 | P a g e