Технологии для разработчиков | C#
Объектно-ориентированный и типобезопасный язык программирования, имеющий корни в языках семейства C и поддерживающий компонентно-ориентированное программирование.
Этот браузер больше не поддерживается.
Выполните обновление до Microsoft Edge, чтобы воспользоваться новейшими функциями, обновлениями для системы безопасности и технической поддержкой.
Hello,
I am working on a WPF application for a store (exam project). I have implemented authorization with roles (Admin, Manager, User) and a block after 3 failed attempts. But sometimes I get a NullReferenceException and the block doesn't always save to the database. Also I'm not sure about my architecture.
Below is my full code. Please tell me what I can improve.
Thank you!
Problem 1: NullReferenceException**
Sometimes when I enter a wrong password, I get a NullReferenceException. I think it happens when the user is not found in the database, but I'm not sure. I added null checking but the error still appears randomly.
<Code block 1: Models>
// ---------------------------- Models.cs ----------------------------
// using System;
// using System.Collections.Generic;
// using System.ComponentModel.DataAnnotations;
// using System.ComponentModel.DataAnnotations.Schema;
//
// namespace Store
// {
// public class Product
// {
// public int Id { get; set; }
// public string Name { get; set; }
// public string Description { get; set; }
// public decimal Price { get; set; }
// public int Stock { get; set; }
// public int Discount { get; set; }
// public string ImagePath { get; set; }
// public int CategoryId { get; set; }
// public int ManufacturerId { get; set; }
// public virtual Category Category { get; set; }
// public virtual Manufacturer Manufacturer { get; set; }
// }
//
// public class Category
// {
// public int Id { get; set; }
// public string Name { get; set; }
// public virtual ICollection<Product> Products { get; set; }
// }
//
// public class Manufacturer
// {
// public int Id { get; set; }
// public string Name { get; set; }
// public virtual ICollection<Product> Products { get; set; }
// }
//
// public class Order
// {
// public int Id { get; set; }
// public DateTime OrderDate { get; set; }
// public DateTime? PickupDate { get; set; }
// public string Status { get; set; }
// public string PickupAddress { get; set; }
// public int UserId { get; set; }
// public virtual User User { get; set; }
// public virtual ICollection<OrderItem> OrderItems { get; set; }
// }
//
// public class OrderItem
// {
// public int Id { get; set; }
// public int OrderId { get; set; }
// public int ProductId { get; set; }
// public int Quantity { get; set; }
// public virtual Order Order { get; set; }
// public virtual Product Product { get; set; }
// }
//
// public class User
// {
// public int Id { get; set; }
// public string Login { get; set; }
// public string Password { get; set; }
// public string FullName { get; set; }
// public string Role { get; set; }
// public bool IsBlocked { get; set; }
// }
// }
<Code block 2: DbContext>
// ---------------------------- ФАЙЛ 2: StoreContext.cs ----------------------------
// using Microsoft.EntityFrameworkCore;
//
// namespace Store
// {
// public class StoreContext : DbContext
// {
// public DbSet<Product> Products { get; set; }
// public DbSet<Category> Categories { get; set; }
// public DbSet<Manufacturer> Manufacturers { get; set; }
// public DbSet<Order> Orders { get; set; }
// public DbSet<OrderItem> OrderItems { get; set; }
// public DbSet<User> Users { get; set; }
//
// protected override void OnConfiguring(DbContextOptionsBuilder options)
// => options.UseSqlServer("Server=(localdb)\\MSSQLLocalDB;Database=StoreDB;Trusted_Connection=True;");
//
// protected override void OnModelCreating(ModelBuilder modelBuilder)
// {
// modelBuilder.Entity<OrderItem>()
// .HasKey(oi => new { oi.OrderId, oi.ProductId });
//
// modelBuilder.Entity<Order>()
// .Property(o => o.Status)
// .HasDefaultValue("Новый");
//
// modelBuilder.Entity<User>()
// .HasIndex(u => u.Login)
// .IsUnique();
//
// modelBuilder.Entity<Category>().HasData(
// new Category { Id = 1, Name = "Кроссовки" },
// new Category { Id = 2, Name = "Ботинки" },
// new Category { Id = 3, Name = "Сандалии" }
// );
//
// modelBuilder.Entity<Manufacturer>().HasData(
// new Manufacturer { Id = 1, Name = "Nike" },
// new Manufacturer { Id = 2, Name = "Adidas" },
// new Manufacturer { Id = 3, Name = "Reebok" }
// );
//
// modelBuilder.Entity<User>().HasData(
// new User { Id = 1, Login = "admin", Password = "admin123", FullName = "Администратор", Role = "Администратор", IsBlocked = false },
// new User { Id = 2, Login = "manager", Password = "manager123", FullName = "Менеджер Иванов", Role = "Менеджер", IsBlocked = false },
// new User { Id = 3, Login = "user", Password = "user123", FullName = "Клиент Петров", Role = "Клиент", IsBlocked = false }
// );
// }
// }
// }
<Code block 3:
// ---------------------------- ФАЙЛ 3: MainWindow.xaml ----------------------------
// <Window x:Class="Store.MainWindow"
// xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
// xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
// Title="Магазин обуви" Height="650" Width="1000">
//
// <Grid Margin="10">
// <Grid.RowDefinitions>
// <RowDefinition Height="Auto"/>
// <RowDefinition Height="Auto"/>
// <RowDefinition Height="*"/>
// <RowDefinition Height="Auto"/>
// </Grid.RowDefinitions>
//
// <TextBlock Text="Магазин обуви" FontSize="24" FontWeight="Bold" HorizontalAlignment="Center" Margin="5"/>
//
// <StackPanel Grid.Row="1" Orientation="Horizontal" Margin="0,10">
// <TextBlock Text="Поиск:" VerticalAlignment="Center" Margin="5"/>
// <TextBox x:Name="SearchBox" Width="200" Margin="5" TextChanged="SearchBox_TextChanged"/>
//
// <TextBlock Text="Поставщик:" VerticalAlignment="Center" Margin="20,5,5,5"/>
// <ComboBox x:Name="FilterCombo" Width="150" Margin="5" SelectionChanged="FilterCombo_SelectionChanged"/>
//
// <TextBlock Text="Сортировка:" VerticalAlignment="Center" Margin="20,5,5,5"/>
// <ComboBox x:Name="SortCombo" Width="180" Margin="5" SelectionChanged="SortCombo_SelectionChanged"/>
// </StackPanel>
//
// <DataGrid x:Name="ProductsGrid" Grid.Row="2" AutoGenerateColumns="False" IsReadOnly="True"
// SelectionMode="Single" Margin="0,10" AlternatingRowBackground="LightGray"
// RowStyle="{StaticResource ProductRowStyle}">
// <DataGrid.Columns>
// <DataGridTextColumn Header="Название" Binding="{Binding Name}" Width="150"/>
// <DataGridTextColumn Header="Категория" Binding="{Binding Category.Name}" Width="100"/>
// <DataGridTextColumn Header="Производитель" Binding="{Binding Manufacturer.Name}" Width="100"/>
// <DataGridTextColumn Header="Цена" Binding="{Binding Price, StringFormat='{0:C}'}" Width="80"/>
// <DataGridTextColumn Header="Скидка" Binding="{Binding Discount}" Width="60"/>
// <DataGridTextColumn Header="Цена со скидкой" Binding="{Binding FinalPrice, StringFormat='{0:C}'}" Width="100"/>
// <DataGridTextColumn Header="В наличии" Binding="{Binding Stock}" Width="80"/>
// </DataGrid.Columns>
// </DataGrid>
//
// <StackPanel Grid.Row="3" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,10">
// <Button x:Name="LoginBtn" Content="Войти" Click="LoginBtn_Click" Width="80" Margin="5"/>
// <Button x:Name="GuestBtn" Content="Гость" Click="GuestBtn_Click" Width="80" Margin="5"/>
// <Button x:Name="OrdersBtn" Content="Заказы" Click="OrdersBtn_Click" Width="80" Margin="5" Visibility="Collapsed"/>
// <Button x:Name="AddProductBtn" Content="Добавить товар" Click="AddProductBtn_Click" Width="120" Margin="5" Visibility="Collapsed"/>
// <Button x:Name="EditProductBtn" Content="Редактировать" Click="EditProductBtn_Click" Width="100" Margin="5" Visibility="Collapsed"/>
// <Button x:Name="DeleteProductBtn" Content="Удалить" Click="DeleteProductBtn_Click" Width="80" Margin="5" Visibility="Collapsed"/>
// <Button x:Name="UnblockUserBtn" Content="Разблокировать пользователя" Click="UnblockUserBtn_Click" Width="180" Margin="5" Visibility="Collapsed"/>
// <Button x:Name="LogoutBtn" Content="Выйти" Click="LogoutBtn_Click" Width="80" Margin="5" Visibility="Collapsed"/>
// </StackPanel>
// </Grid>
// </Window>
--------
// ---------------------------- MainWindow.xaml.cs ----------------------------
// using System.Linq;
// using System.Windows;
// using Microsoft.EntityFrameworkCore;
//
// namespace Store
// {
// public partial class MainWindow : Window
// {
// private StoreContext db = new StoreContext();
// private User currentUser = null;
//
// public MainWindow()
// {
// InitializeComponent();
// LoadFiltersAndSorts();
// LoadProducts();
// }
//
// private void LoadFiltersAndSorts()
// {
// var suppliers = db.Products.Select(p => p.Manufacturer.Name).Distinct().ToList();
// suppliers.Insert(0, "Все поставщики");
// FilterCombo.ItemsSource = suppliers;
// FilterCombo.SelectedIndex = 0;
//
// SortCombo.ItemsSource = new[] { "По возрастанию количества", "По убыванию количества" };
// SortCombo.SelectedIndex = 0;
// }
//
// private void LoadProducts()
// {
// var query = db.Products
// .Include(p => p.Category)
// .Include(p => p.Manufacturer)
// .AsQueryable();
//
// string search = SearchBox.Text?.ToLower();
// if (!string.IsNullOrEmpty(search))
// query = query.Where(p => p.Name.ToLower().Contains(search) || p.Description.ToLower().Contains(search));
//
// if (FilterCombo.SelectedIndex > 0)
// query = query.Where(p => p.Manufacturer.Name == FilterCombo.SelectedItem.ToString());
//
// if (SortCombo.SelectedIndex == 0)
// query = query.OrderBy(p => p.Stock);
// else
// query = query.OrderByDescending(p => p.Stock);
//
// var list = query.ToList().Select(p => new
// {
// p.Id,
// p.Name,
// p.Category,
// p.Description,
// p.Manufacturer,
// p.Price,
// p.Discount,
// FinalPrice = p.Price * (1 - p.Discount / 100m),
// p.Stock,
// p.ImagePath
// }).ToList();
//
// ProductsGrid.ItemsSource = list;
// }
//
// private void SearchBox_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e) => LoadProducts();
// private void FilterCombo_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e) => LoadProducts();
// private void SortCombo_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e) => LoadProducts();
//
// private void LoginBtn_Click(object sender, RoutedEventArgs e)
// {
// var loginWin = new LoginWindow(db);
// if (loginWin.ShowDialog() == true)
// {
// currentUser = loginWin.AuthenticatedUser;
// UpdateUIForRole();
// }
// }
//
// private void GuestBtn_Click(object sender, RoutedEventArgs e)
// {
// currentUser = null;
// UpdateUIForRole();
// }
//
// private void UpdateUIForRole()
// {
// bool isAdmin = currentUser != null && currentUser.Role == "Администратор";
// bool isManager = currentUser != null && (currentUser.Role == "Администратор" || currentUser.Role == "Менеджер");
//
// OrdersBtn.Visibility = isManager ? Visibility.Visible : Visibility.Collapsed;
// AddProductBtn.Visibility = isAdmin ? Visibility.Visible : Visibility.Collapsed;
// EditProductBtn.Visibility = isAdmin ? Visibility.Visible : Visibility.Collapsed;
// DeleteProductBtn.Visibility = isAdmin ? Visibility.Visible : Visibility.Collapsed;
// UnblockUserBtn.Visibility = isAdmin ? Visibility.Visible : Visibility.Collapsed;
// LogoutBtn.Visibility = currentUser != null ? Visibility.Visible : Visibility.Collapsed;
// LoginBtn.Visibility = currentUser == null ? Visibility.Visible : Visibility.Collapsed;
// GuestBtn.Visibility = currentUser == null ? Visibility.Visible : Visibility.Collapsed;
//
// if (currentUser != null)
// MessageBox.Show($"Вы успешно авторизовались. Добро пожаловать, {currentUser.FullName}");
//
// LoadProducts();
// }
//
// private void OrdersBtn_Click(object sender, RoutedEventArgs e)
// {
// new OrdersWindow(db).ShowDialog();
// }
//
// private void AddProductBtn_Click(object sender, RoutedEventArgs e)
// {
// var win = new ProductEditWindow(db);
// if (win.ShowDialog() == true)
// LoadProducts();
// }
//
// private void EditProductBtn_Click(object sender, RoutedEventArgs e)
// {
// var selected = ProductsGrid.SelectedItem;
// if (selected == null)
// {
// MessageBox.Show("Выберите товар для редактирования");
// return;
// }
//
// int id = (int)selected.GetType().GetProperty("Id").GetValue(selected);
// var product = db.Products.Find(id);
// var win = new ProductEditWindow(db, product);
// if (win.ShowDialog() == true)
// LoadProducts();
// }
//
// private void DeleteProductBtn_Click(object sender, RoutedEventArgs e)
// {
// var selected = ProductsGrid.SelectedItem;
// if (selected == null)
// {
// MessageBox.Show("Выберите товар для удаления");
// return;
// }
//
// int id = (int)selected.GetType().GetProperty("Id").GetValue(selected);
// var product = db.Products.Find(id);
//
// if (db.OrderItems.Any(oi => oi.ProductId == id))
// {
// MessageBox.Show("Товар присутствует в заказе, удалить нельзя");
// return;
// }
//
// if (MessageBox.Show($"Удалить товар '{product.Name}'?", "Подтверждение", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
// {
// db.Products.Remove(product);
// db.SaveChanges();
// LoadProducts();
// }
// }
//
// private void UnblockUserBtn_Click(object sender, RoutedEventArgs e)
// {
// var blockedUsers = db.Users.Where(u => u.IsBlocked).ToList();
// if (!blockedUsers.Any())
// {
// MessageBox.Show("Нет заблокированных пользователей");
// return;
// }
//
// var unblockWindow = new UnblockWindow(db, blockedUsers);
// if (unblockWindow.ShowDialog() == true)
// {
// db.SaveChanges();
// MessageBox.Show("Пользователь разблокирован");
// }
// }
//
// private void LogoutBtn_Click(object sender, RoutedEventArgs e)
// {
// currentUser = null;
// UpdateUIForRole();
// }
// }
// }
// ---------------------------- App.xaml ----------------------------
// <Application x:Class="Store.App"
// xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
// xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
// StartupUri="MainWindow.xaml">
// <Application.Resources>
// <Style x:Key="ProductRowStyle" TargetType="DataGridRow">
// <Style.Triggers>
// <DataTrigger Binding="{Binding Discount}" Value="0">
// <Setter Property="Background" Value="White"/>
// </DataTrigger>
// <DataTrigger Binding="{Binding Discount}" Value="15">
// <Setter Property="Background" Value="#2E8B57"/>
// </DataTrigger>
// <DataTrigger Binding="{Binding Stock}" Value="0">
// <Setter Property="Background" Value="LightBlue"/>
// </DataTrigger>
// </Style.Triggers>
// </Style>
// </Application.Resources>
// </Application>
--------
// ---------------------------- LoginWindow.xaml ----------------------------
// <Window x:Class="Store.LoginWindow"
// xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
// xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
// Title="Авторизация" Height="250" Width="400" WindowStartupLocation="CenterScreen">
//
// <Grid Margin="20">
// <Grid.RowDefinitions>
// <RowDefinition Height="Auto"/>
// <RowDefinition Height="Auto"/>
// <RowDefinition Height="Auto"/>
// <RowDefinition Height="Auto"/>
// </Grid.RowDefinitions>
//
// <TextBlock Text="Вход в систему" FontSize="20" FontWeight="Bold" HorizontalAlignment="Center" Margin="0,0,0,20"/>
//
// <StackPanel Grid.Row="1" Orientation="Horizontal" Margin="0,5">
// <TextBlock Text="Логин:" Width="80" VerticalAlignment="Center"/>
// <TextBox x:Name="LoginBox" Width="200"/>
// </StackPanel>
//
// <StackPanel Grid.Row="2" Orientation="Horizontal" Margin="0,5">
// <TextBlock Text="Пароль:" Width="80" VerticalAlignment="Center"/>
// <PasswordBox x:Name="PasswordBox" Width="200"/>
// </StackPanel>
//
// <StackPanel Grid.Row="3" Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,20">
// <Button x:Name="LoginButton" Content="Войти" Width="80" Margin="5" Click="LoginButton_Click"/>
// <Button x:Name="GuestButton" Content="Гость" Width="80" Margin="5" Click="GuestButton_Click"/>
// </StackPanel>
// </Grid>
// </Window>
------------
// ---------------------------- ФАЙЛ 7: LoginWindow.xaml.cs ----------------------------
// using System.Linq;
// using System.Windows;
//
// namespace Store
// {
// public partial class LoginWindow : Window
// {
// private StoreContext db;
// private int failedAttempts = 0;
// private string currentLogin = null;
// public User AuthenticatedUser { get; private set; }
//
// public LoginWindow(StoreContext context)
// {
// InitializeComponent();
// db = context;
// }
//
// private void LoginButton_Click(object sender, RoutedEventArgs e)
// {
// string login = LoginBox.Text;
// string password = PasswordBox.Password;
//
// var user = db.Users.FirstOrDefault(u => u.Login == login);
//
// if (user == null)
// {
// HandleFailedAttempt(null, login);
// return;
// }
//
// if (user.IsBlocked)
// {
// MessageBox.Show("Вы заблокированы. Обратитесь к администратору",
// "Доступ запрещён", MessageBoxButton.OK, MessageBoxImage.Warning);
// return;
// }
//
// if (user.Password != password)
// {
// HandleFailedAttempt(user, login);
// return;
// }
//
// // Успешный вход
// AuthenticatedUser = user;
// DialogResult = true;
// Close();
// }
//
// private void HandleFailedAttempt(User user, string login)
// {
// if (currentLogin != login)
// {
// currentLogin = login;
// failedAttempts = 1;
// }
// else
// {
// failedAttempts++;
// }
//
// MessageBox.Show($"Неверный логин или пароль. Попытка {failedAttempts} из 3",
// "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
//
// if (user != null && failedAttempts >= 3)
// {
// user.IsBlocked = true;
// db.SaveChanges();
// MessageBox.Show("Вы заблокированы. Обратитесь к администратору",
// "Доступ запрещён", MessageBoxButton.OK, MessageBoxImage.Warning);
// Close();
// }
// else if (user == null && failedAttempts >= 3)
// {
// MessageBox.Show("Вы заблокированы. Обратитесь к администратору",
// "Доступ запрещён", MessageBoxButton.OK, MessageBoxImage.Warning);
// Close();
// }
// }
//
// private void GuestButton_Click(object sender, RoutedEventArgs e)
// {
// AuthenticatedUser = null;
// DialogResult = false;
// Close();
// }
// }
// }
// ---------------------------- ФАЙЛ 8: ProductEditWindow.xaml ----------------------------
// <Window x:Class="Store.ProductEditWindow"
// xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
// xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
// Title="Товар" Height="500" Width="450" WindowStartupLocation="CenterScreen">
//
// <Grid Margin="10">
// <Grid.RowDefinitions>
// <RowDefinition Height="Auto"/>
// <RowDefinition Height="Auto"/>
// <RowDefinition Height="Auto"/>
// <RowDefinition Height="Auto"/>
// <RowDefinition Height="Auto"/>
// <RowDefinition Height="Auto"/>
// <RowDefinition Height="Auto"/>
// <RowDefinition Height="Auto"/>
// <RowDefinition Height="Auto"/>
// <RowDefinition Height="Auto"/>
// </Grid.RowDefinitions>
//
// <TextBlock Text="Редактирование товара" FontSize="16" FontWeight="Bold" Grid.Row="0" Margin="0,0,0,10"/>
//
// <StackPanel Grid.Row="1" Orientation="Horizontal" Margin="0,5">
// <TextBlock Text="ID:" Width="100"/>
// <TextBox x:Name="IdBox" IsReadOnly="True" Width="250"/>
// </StackPanel>
//
// <StackPanel Grid.Row="2" Orientation="Horizontal" Margin="0,5">
// <TextBlock Text="Название:*" Width="100"/>
// <TextBox x:Name="NameBox" Width="250"/>
// </StackPanel>
//
// <StackPanel Grid.Row="3" Orientation="Horizontal" Margin="0,5">
// <TextBlock Text="Категория:*" Width="100"/>
// <ComboBox x:Name="CategoryCombo" Width="250" DisplayMemberPath="Name"/>
// </StackPanel>
//
// <StackPanel Grid.Row="4" Orientation="Horizontal" Margin="0,5">
// <TextBlock Text="Производитель:*" Width="100"/>
// <ComboBox x:Name="ManufacturerCombo" Width="250" DisplayMemberPath="Name"/>
// </StackPanel>
//
// <StackPanel Grid.Row="5" Orientation="Horizontal" Margin="0,5">
// <TextBlock Text="Цена:*" Width="100"/>
// <TextBox x:Name="PriceBox" Width="250"/>
// </StackPanel>
//
// <StackPanel Grid.Row="6" Orientation="Horizontal" Margin="0,5">
// <TextBlock Text="Количество:*" Width="100"/>
// <TextBox x:Name="StockBox" Width="250"/>
// </StackPanel>
//
// <StackPanel Grid.Row="7" Orientation="Horizontal" Margin="0,5">
// <TextBlock Text="Скидка (%)" Width="100"/>
// <TextBox x:Name="DiscountBox" Text="0" Width="250"/>
// </StackPanel>
//
// <StackPanel Grid.Row="8" Orientation="Horizontal" Margin="0,5">
// <TextBlock Text="Описание:" Width="100"/>
// <TextBox x:Name="DescriptionBox" Width="250" Height="60" TextWrapping="Wrap"/>
// </StackPanel>
//
// <StackPanel Grid.Row="9" Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,20">
// <Button x:Name="SaveBtn" Content="Сохранить" Width="100" Margin="5" Click="SaveBtn_Click"/>
// <Button x:Name="CancelBtn" Content="Отмена" Width="100" Margin="5" Click="CancelBtn_Click"/>
// </StackPanel>
// </Grid>
// </Window>
Problem 2: Block doesn't save to database**
When a user enters the wrong password 3 times, I set IsBlocked = true. But after restarting the application, the user is not blocked anymore. It seems like the change is not saved to the database, or maybe I am not calling SaveChanges() correctly.
// ---------------------------- ФАЙЛ 9: ProductEditWindow.xaml.cs ----------------------------
// using System.Linq;
// using System.Windows;
//
// namespace Store
// {
// public partial class ProductEditWindow : Window
// {
// private StoreContext db;
// private Product editingProduct;
//
// public ProductEditWindow(StoreContext context, Product product = null)
// {
// InitializeComponent();
// db = context;
// editingProduct = product ?? new Product();
//
// CategoryCombo.ItemsSource = db.Categories.ToList();
// ManufacturerCombo.ItemsSource = db.Manufacturers.ToList();
//
// if (product != null)
// {
// IdBox.Text = product.Id.ToString();
// NameBox.Text = product.Name;
// CategoryCombo.SelectedItem = db.Categories.FirstOrDefault(c => c.Id == product.CategoryId);
// ManufacturerCombo.SelectedItem = db.Manufacturers.FirstOrDefault(m => m.Id == product.ManufacturerId);
// PriceBox.Text = product.Price.ToString();
// StockBox.Text = product.Stock.ToString();
// DiscountBox.Text = product.Discount.ToString();
// DescriptionBox.Text = product.Description;
// }
// }
//
// private void SaveBtn_Click(object sender, RoutedEventArgs e)
// {
// if (string.IsNullOrWhiteSpace(NameBox.Text))
// {
// MessageBox.Show("Введите название товара");
// return;
// }
// if (CategoryCombo.SelectedItem == null)
// {
// MessageBox.Show("Выберите категорию");
// return;
// }
// if (ManufacturerCombo.SelectedItem == null)
// {
// MessageBox.Show("Выберите производителя");
// return;
// }
// if (!decimal.TryParse(PriceBox.Text, out decimal price) || price < 0)
// {
// MessageBox.Show("Введите корректную цену");
// return;
// }
// if (!int.TryParse(StockBox.Text, out int stock) || stock < 0)
// {
// MessageBox.Show("Введите корректное количество");
// return;
// }
// if (!int.TryParse(DiscountBox.Text, out int discount) || discount < 0 || discount > 100)
// {
// MessageBox.Show("Скидка должна быть от 0 до 100");
// return;
// }
//
// editingProduct.Name = NameBox.Text;
// editingProduct.CategoryId = ((Category)CategoryCombo.SelectedItem).Id;
// editingProduct.ManufacturerId = ((Manufacturer)ManufacturerCombo.SelectedItem).Id;
// editingProduct.Price = price;
// editingProduct.Stock = stock;
// editingProduct.Discount = discount;
// editingProduct.Description = DescriptionBox.Text;
//
// if (editingProduct.Id == 0)
// db.Products.Add(editingProduct);
//
// db.SaveChanges();
// DialogResult = true;
// Close();
// }
//
// private void CancelBtn_Click(object sender, RoutedEventArgs e)
// {
// DialogResult = false;
// Close();
// }
// }
// }
ФАЙЛ 10: OrdersWindow.xaml ----------------------------
// <Window x:Class="Store.OrdersWindow"
// xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
// xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
// Title="Заказы" Height="450" Width="800" WindowStartupLocation="CenterScreen">
//
// <Grid Margin="10">
// <Grid.RowDefinitions>
// <RowDefinition Height="Auto"/>
// <RowDefinition Height="*"/>
// </Grid.RowDefinitions>
//
// <TextBlock Text="Список заказов" FontSize="20" FontWeight="Bold" HorizontalAlignment="Center" Margin="5"/>
//
// <DataGrid x:Name="OrdersGrid" Grid.Row="1" AutoGenerateColumns="False" IsReadOnly="True" Margin="0,10">
// <DataGrid.Columns>
// <DataGridTextColumn Header="№ заказа" Binding="{Binding Id}" Width="80"/>
// <DataGridTextColumn Header="Клиент" Binding="{Binding User.FullName}" Width="150"/>
// <DataGridTextColumn Header="Дата заказа" Binding="{Binding OrderDate, StringFormat='dd.MM.yyyy'}" Width="100"/>
// <DataGridTextColumn Header="Статус" Binding="{Binding Status}" Width="100"/>
// <DataGridTextColumn Header="Адрес выдачи" Binding="{Binding PickupAddress}" Width="150"/>
// <DataGridTextColumn Header="Сумма" Binding="{Binding TotalAmount, StringFormat='{0:C}'}" Width="100"/>
// </DataGrid.Columns>
// </DataGrid>
// </Grid>
// </Window>
Объектно-ориентированный и типобезопасный язык программирования, имеющий корни в языках семейства C и поддерживающий компонентно-ориентированное программирование.
---------------------------- ФАЙЛ 11: OrdersWindow.xaml.cs ----------------------------
// using System.Linq;
// using System.Windows;
// using Microsoft.EntityFrameworkCore;
//
// namespace Store
// {
// public partial class OrdersWindow : Window
// {
// private StoreContext db;
//
// public OrdersWindow(StoreContext context)
// {
// InitializeComponent();
// db = context;
// LoadOrders();
// }
//
// private void LoadOrders()
// {
// var orders = db.Orders
// .Include(o => o.User)
// .Include(o => o.OrderItems)
// .ThenInclude(oi => oi.Product)
// .ToList()
// .Select(o => new
// {
// o.Id,
// o.User,
// o.OrderDate,
// o.Status,
// o.PickupAddress,
// TotalAmount = o.OrderItems.Sum(oi => oi.Quantity * oi.Product.Price * (1 - oi.Product.Discount / 100m))
// })
// .ToList();
//
// OrdersGrid.ItemsSource = orders;
// }
// }
// }
---------------------------- ФАЙЛ 12: UnblockWindow.xaml ----------------------------
// <Window x:Class="Store.UnblockWindow"
// xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
// xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
// Title="Разблокировка пользователей" Height="400" Width="500" WindowStartupLocation="CenterScreen">
//
// <Grid>
// <Grid.RowDefinitions>
// <RowDefinition Height="*"/>
// <RowDefinition Height="Auto"/>
// </Grid.RowDefinitions>
//
// <ListBox x:Name="UsersList" DisplayMemberPath="FullName" Margin="10" Grid.Row="0"/>
//
// <Button x:Name="UnblockBtn" Content="Разблокировать выбранного" Click="UnblockBtn_Click"
// Width="200" Height="35" Margin="10" Grid.Row="1" HorizontalAlignment="Center"/>
// </Grid>
// </Window>
---------------------------- ФАЙЛ 13: UnblockWindow.xaml.cs ----------------------------
// using System.Collections.Generic;
// using System.Linq;
// using System.Windows;
//
// namespace Store
// {
// public partial class UnblockWindow : Window
// {
// private StoreContext db;
// private List<User> blockedUsers;
//
// public UnblockWindow(StoreContext context, List<User> users)
// {
// InitializeComponent();
// db = context;
// blockedUsers = users;
// UsersList.ItemsSource = blockedUsers;
// }
//
// private void UnblockBtn_Click(object sender, RoutedEventArgs e)
// {
// var selected = UsersList.SelectedItem as User;
// if (selected != null)
// {
// selected.IsBlocked = false;
// DialogResult = true;
// Close();
// }
// else
// {
// MessageBox.Show("Выберите пользователя для разблокировки");
// }
// }
// }
// }
... and so on up to 13 blocks