<|start_filename|>02-Enhance/ExpenseItDemo.Data/Model/Expense.cs<|end_filename|>
﻿using System.ComponentModel;

namespace ExpenseItDemo.Data.Model
{
    public class Expense: INotifyPropertyChanged
    {
        private double _cost;
        private string _description;
        private string _type;
        private int _expenseId;
        private int _employeeId;

        public string Type
        {
            get { return _type; }
            set
            {
                _type = value;
                OnPropertyChanged("Type");
            }
        }

        public string Description
        {
            get { return _description; }
            set
            {
                _description = value;
                OnPropertyChanged("Description");
            }
        }

        public double Cost
        {
            get { return _cost; }
            set
            {
                _cost = value;
                OnPropertyChanged("Cost");
            }
        }

        
        public int ExpenseId
        {
            get { return _expenseId; }
            set
            {
                _expenseId = value;
                OnPropertyChanged("ExpenseId");
            }
        }

        public int EmployeeId
        {
            get { return _employeeId; }
            set
            {
                _employeeId = value;
                OnPropertyChanged("EmployeeId");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged(string propName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
        }

       

    }
}


<|start_filename|>02-Enhance/ExpenseItDemo.Data/Services/DatabaseService.cs<|end_filename|>
﻿using ExpenseItDemo.Data.Model;
using System.Collections.Generic;
using System.Data.OleDb;

namespace ExpenseItDemo.Data.Services
{
    public class DatabaseService
    {
        private OleDbConnection connection;
        public DatabaseService()
        {
            connection = new OleDbConnection();
            string location = System.Reflection.Assembly.GetExecutingAssembly().Location;
            int index = location.LastIndexOf("\\");
            string path = $"{location.Substring(0, index)}\\Expenses.mdb";
            connection.ConnectionString = $"Provider = Microsoft.Jet.Oledb.4.0; Data Source = {path}";
        }

        public List<Employee> GetEmployees()
        {
            OleDbCommand command = new OleDbCommand();
            if (connection.State != System.Data.ConnectionState.Open)
            {
                connection.Open();
            }

            List<Employee> employees = new List<Employee>();

            command.Connection = connection;
            command.CommandText = "SELECT * FROM Employees";
            using (OleDbDataReader reader = command.ExecuteReader())
            {
                while (reader.Read())
                {
                    Employee employee = new Employee
                    {
                        EmployeeId = reader.GetInt32(0),
                        FirstName = reader.GetString(1),
                        LastName = reader.GetString(2),
                        Type = reader.GetString(3),
                        Email = reader.GetString(4)
                    };

                    employees.Add(employee);
                }
            }

            return employees;
        }

        public Employee GetEmployeeById(int employeeId)
        {
            OleDbCommand command = new OleDbCommand();
            if (connection.State != System.Data.ConnectionState.Open)
            {
                connection.Open();
            }

            Employee employee = null;

            command.Connection = connection;
            command.CommandText = "SELECT * FROM Employees WHERE Id=@EmployeeId";
            command.Parameters.AddWithValue("EmployeeId", employeeId);
            using (OleDbDataReader reader = command.ExecuteReader())
            {
                while (reader.Read())
                {
                    employee = new Employee
                    {
                        EmployeeId = reader.GetInt32(0),
                        FirstName = reader.GetString(1),
                        LastName = reader.GetString(2),
                        Type = reader.GetString(3),
                        Email = reader.GetString(4),
                        CostCenterId = reader.GetInt32(5)
                    };
                }
            }

            return employee;
        }

        public List<Employee> GetEmployeesByType(string type)
        {
            OleDbCommand command = new OleDbCommand();
            if (connection.State != System.Data.ConnectionState.Open)
            {
                connection.Open();
            }

            List<Employee> employees = new List<Employee>();

            command.Connection = connection;
            command.CommandText = "SELECT * FROM Employees WHERE Type=@Type";
            command.Parameters.AddWithValue("Type", type);
            using (OleDbDataReader reader = command.ExecuteReader())
            {
                while (reader.Read())
                {
                    Employee employee = new Employee
                    {
                        EmployeeId = reader.GetInt32(0),
                        FirstName = reader.GetString(1),
                        LastName = reader.GetString(2),
                        Type = reader.GetString(3),
                        Email = reader.GetString(4),
                        CostCenterId = reader.GetInt32(5)
                    };

                    employees.Add(employee);
                }
            }

            return employees;
        }

        public List<Expense> GetExpensesByEmployee(int employeeId)
        {
            OleDbCommand command = new OleDbCommand();
            if (connection.State != System.Data.ConnectionState.Open)
            {
                connection.Open();
            }

            List<Expense> expenses = new List<Expense>();

            command.Connection = connection;
            command.CommandText = "SELECT * FROM Expenses WHERE EmployeeId=@EmployeeId";
            command.Parameters.AddWithValue("EmployeeId", employeeId);
            using (OleDbDataReader reader = command.ExecuteReader())
            {
                while (reader.Read())
                {
                    Expense expense = new Expense();
                    expense.ExpenseId = reader.GetInt32(0);
                    expense.Type = reader.GetString(1);
                    expense.Description = reader.GetString(2);
                    expense.Cost = reader.GetDouble(3);
                    expense.EmployeeId = employeeId;

                    expenses.Add(expense);
                }
            }

            return expenses;
        }
    }
}


<|start_filename|>02-Enhance/ExpenseItDemo/ExpenseReport.cs<|end_filename|>
// // Copyright (c) Microsoft. All rights reserved.
// // Licensed under the MIT license. See LICENSE file in the project root for full license information.

using ExpenseItDemo.Data.Model;
using ExpenseItDemo.Data.Services;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;

// EventHandler
// ObservableCollection

// INotifyPropertyChanged, PropertyChangedEventArgs

namespace ExpenseItDemo
{
    public class ExpenseReport : INotifyPropertyChanged
    {
        private string _email;
        private int _costCenterId;
        private string _employeeId;
        private double _totalExpenses;

        public ExpenseReport(int employeeId)
        {
            DatabaseService dbService = new DatabaseService();
            Employee employee = dbService.GetEmployeeById(employeeId);

            Email = employee.Email;
            CostCenterId = employee.CostCenterId;
            EmployeeId = employeeId.ToString();

            List<Expense> expenses = dbService.GetExpensesByEmployee(employeeId);
            Expenses = new ExpensesCollection(expenses);
            Expenses.ExpenseCostChanged += OnExpenseCostChanged;
        }

        public string Email
        {
            get { return _email; }
            set
            {
                _email = value;
                OnPropertyChanged("Email");
            }
        }

        public int CostCenterId
        {
            get { return _costCenterId; }
            set
            {
                _costCenterId = value;
                OnPropertyChanged("CostCenterId");
            }
        }

        public string EmployeeId
        {
            get { return _employeeId; }
            set
            {
                _employeeId = value;
                OnPropertyChanged("EmployeeId");
            }
        }

        public double TotalExpenses
        {
            // calculated property, no setter
            get
            {
                RecalculateTotalExpense();
                return _totalExpenses;
            }
        }

        public ExpensesCollection Expenses { get; }
        public event PropertyChangedEventHandler PropertyChanged;

        private void OnExpenseCostChanged(object sender, EventArgs e)
        {
            OnPropertyChanged("TotalExpenses");
        }

        private void RecalculateTotalExpense()
        {
            _totalExpenses = 0;
            foreach (var item in Expenses)
                _totalExpenses += item.Cost;
        }

        private void OnPropertyChanged(string propName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
        }
    }
}

<|start_filename|>02-Enhance/ExpenseItDemo/ExpensesCollection.cs<|end_filename|>
// // Copyright (c) Microsoft. All rights reserved.
// // Licensed under the MIT license. See LICENSE file in the project root for full license information.

using ExpenseItDemo.Data.Model;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;

namespace ExpenseItDemo
{
    public class ExpensesCollection : ObservableCollection<Expense>
    {
        public ExpensesCollection(IEnumerable<Expense> expenses)
        {
            foreach (Expense expense in expenses)
            {
                Add(expense);
            }
        }

        public event EventHandler ExpenseCostChanged;

        public new void Add(Expense item)
        {
            if (item != null)
            {
                item.PropertyChanged += ExpensePropertyChanged;
            }
            base.Add(item);
        }

        private void ExpensePropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "Cost")
            {
                OnExpenseCostChanged(this, new EventArgs());
            }
        }

        private void OnExpenseCostChanged(object sender, EventArgs args)
        {
            ExpenseCostChanged?.Invoke(sender, args);
        }
    }
}