# AlfaToad.DefaultScreens NuGet-пакет **готовых экранных форм** для типового WinForms-приложения с ролевым доступом. Использует [AlfaToad.CustomControls](https://www.nuget.org/packages/AlfaToad.CustomControls) и [AlfaToad.DataSetCRUDS](https://www.nuget.org/packages/AlfaToad.DataSetCRUDS). ## Возможности | Экран | Описание | |-------|----------| | `LoginScreenForm` | Вход по логину/паролю из DataSet + режим гостя | | `MainShellForm` | Главная форма с логотипом, навигацией, кнопкой «Назад» и отображением текущего экрана в заголовке | | `CatalogScreenForm` | Каталог на `ScrollableDetailPanel` с учётом роли | | `OrderListScreenForm` | Заказы на `ScrollableOrderPanel` | | `ApplicationNavigator` | Полный сценарий: вход → главная → экраны | ### Настройка через `ApplicationScreenSettings` - Заголовки окон, тексты кнопок, подписи полей входа - `Appearance` — палитра цветов (#FFFFFF, #F5DEB3, #DEB887, Arial) - `LogoImagePath`, `ApplicationIconPath`, `NoImagePath` + `ApplyResourcePaths()` - `LoginFormWidth`, `LoginFormHeight`, `LoginLogoHeight` - `DetailFields`, `OrderFields` — карты столбцов БД - `CreateCatalogCrudOptions()` / `CreateOrderCrudOptions()` — параметры CRUD-форм - `BackMenuText` — текст кнопки «Назад» - `ImageResizeWidth` / `ImageResizeHeight` — ресайз фото товара (300×200) Сообщения пользователю — через `AppDialog` (ошибка / предупреждение / информация). ## Установка ```bash dotnet add package AlfaToad.DefaultScreens --version 1.0.5 ``` ## Пример `Program.cs` (Typed DataSet + view persistence) ```csharp using System; using System.Drawing; using System.Windows.Forms; using AlfaToad.CustomControls.Theme; // AppearancePalette — цвета и шрифты using AlfaToad.DataSetCRUDS.Configuration; // DetailRecordFieldMap, OrderRecordFieldMap using AlfaToad.DefaultScreens.Configuration; // ApplicationScreenSettings, WithViewDataPersistence using AlfaToad.DefaultScreens.Navigation; // ApplicationDataContext, ApplicationNavigator using YourApp; // ваш Typed DataSet (MirIgryshkiDataSet) using YourApp.YourDataSetTableAdapters; namespace YourApp { internal static class Program { [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); // ═══════════════════════════════════════════════════════════════ // ШАГ 1. DataSet и TableAdapter-ы // Для view достаточно Fill() — Insert/Update/Delete делает пакет // ═══════════════════════════════════════════════════════════════ var dataSet = new MirIgryshkiDataSet(); // замените на ваш Typed DataSet var tovarTableAdapter = new vCatalogTableAdapter(); var ordersTableAdapter = new vOrdersTableAdapter(); var usersTableAdapter = new vw_UsersLoginTableAdapter(); // Строка подключения — задайте свои значения или используйте User Secrets / App.config var connectionString = "Server=YOUR_SERVER;Database=YOUR_DATABASE;Trusted_Connection=True;"; /* Server=YOUR_SERVER;Database=YOUR_DATABASE;User Id=YOUR_USER;Password=YOUR_PASSWORD; Server=YOUR_SERVER;Database=YOUR_DATABASE;Trusted_Connection=True; */ // ═══════════════════════════════════════════════════════════════ // ШАГ 2. ApplicationScreenSettings — все настройки приложения // ═══════════════════════════════════════════════════════════════ var settings = ApplicationScreenSettings.CreateDefault(); // ── Заголовки окон ────────────────────────────────────────── settings.LoginWindowTitle = "Вход в систему"; // Заголовок формы входа settings.MainWindowTitle = "Информационная система"; // Заголовок главной формы (оболочка) settings.CatalogWindowTitle = "Каталог товаров"; // Заголовок экрана каталога settings.OrdersWindowTitle = "Список заказов"; // Заголовок экрана заказов // ── Тексты кнопок и пунктов меню ──────────────────────────── settings.LoginButtonText = "Войти"; // Кнопка «Войти» на форме входа settings.GuestButtonText = "Войти как гость"; // Кнопка гостевого входа settings.CatalogMenuText = "Каталог"; // Пункт меню «Каталог» на главной форме settings.OrdersMenuText = "Заказы"; // Пункт меню «Заказы» settings.LogoutMenuText = "Выход"; // Пункт меню «Выход» (повторный вход) settings.BackMenuText = "Назад"; // Кнопка возврата на главную форму // ── Экран входа: подписи и размеры ────────────────────────── settings.LoginCaptionLogin = "Логин:"; // Подпись слева от поля логина settings.LoginCaptionPassword = "Пароль:"; // Подпись слева от поля пароля settings.LoginFormWidth = 480; // Ширина формы входа (px) settings.LoginFormHeight = 420; // Высота формы входа (px) — чтобы кнопки не обрезались settings.LoginLogoHeight = 110; // Высота области логотипа на форме входа (px) // ── Пути к ресурсам (загружаются через ApplyResourcePaths) ── settings.LogoImagePath = @"C:\Path\To\Your\Resources\icon.png"; // Логотип → settings.LogoImage settings.ApplicationIconPath = @"C:\Path\To\Your\Resources\icon.ico"; // Иконка приложения → settings.ApplicationIcon settings.NoImagePath = @"C:\Path\To\Your\Resources\picture.png"; // Заглушка «нет фото» → settings.NoImage // Либо задайте Image/Icon напрямую (без путей): // settings.LogoImage = Image.FromFile(@"C:\Path\To\Your\Resources\logo.png"); // settings.ApplicationIcon = new Icon(@"C:\Path\To\Your\Resources\app.ico"); settings.ApplicationIcon = Icon.FromHandle(new Bitmap(@"C:\Path\To\Your\Resources\icon.png").GetHicon()); // Иконка из PNG // settings.NoImage = Image.FromFile(@"C:\Path\To\Your\Resources\picture.png"); settings.ApplyResourcePaths(); // Подставляет LogoImage, NoImage, ApplicationIcon из путей выше // ── Папка изображений товаров ─────────────────────────────── settings.ImagesFolder = @"C:\Path\To\Your\Resources\import"; // Папка с файлами фото (1.jpg, 2.jpg…) // Если пусто — используется подпапка Images рядом с exe // ── Ресайз фото при добавлении/редактировании товара ────── settings.ImageResizeWidth = 300; // Ширина сохраняемого изображения (px) settings.ImageResizeHeight = 200; // Высота сохраняемого изображения (px) // ── Заголовки CRUD-форм ───────────────────────────────────── settings.CatalogAddFormTitle = "Добавление товара"; settings.CatalogEditFormTitle = "Редактирование товара"; settings.OrderAddFormTitle = "Добавление заказа"; settings.OrderEditFormTitle = "Редактирование заказа"; // ═══════════════════════════════════════════════════════════════ // ШАГ 3. AppearancePalette — цвета, шрифты, пороги (стиль экзамена) // Применяется ко всем экранам: вход, главная, каталог, заказы, CRUD-формы // ═══════════════════════════════════════════════════════════════ settings.Appearance = new AppearancePalette { // ── Цвета ─────────────────────────────────────────────── MainBackground = ColorTranslator.FromHtml("#FFFFFF"), // Основной фон форм и строк списка SectionBackground = ColorTranslator.FromHtml("#F5DEB3"), // Фон заголовков, панели кнопок, меню AccentBackground = ColorTranslator.FromHtml("#DEB887"), // Кнопки, акцентные элементы HighlightBackground = ColorTranslator.FromHtml("#FFDEAD"), // Подсветка товара со скидкой > порога SelectedRowBackground = ColorTranslator.FromHtml("#E8EEF8"), // Фон выбранной строки в списке PrimaryText = Color.Black, // Основной цвет текста SeparatorText = Color.Gray, // Текст разделителей BorderColor = Color.Black, // Рамка карточек/строк RowSeparatorColor = Color.Silver, // Линия между строками OutOfStockBackground = ColorTranslator.FromHtml("#ADD8E6"), // Фон строки при кол-ве ≤ 0 StrikethroughPriceColor = Color.Red, // Зачёркнутая цена (при скидке) FinalPriceColor = Color.Black, // Итоговая цена со скидкой // ── Шрифты ────────────────────────────────────────────── FontFamily = "Arial", // Семейство шрифта (по заданию экзамена) BaseFontSize = 9f, // Базовый размер текста в списках и формах TitleFontSize = 10f, // Размер заголовков и имён товаров // ── Пороги ────────────────────────────────────────────── HighlightThresholdPercent = 17m // Скидка > 17% → подсветка HighlightBackground }; // ═══════════════════════════════════════════════════════════════ // ШАГ 4. Имена столбцов БД — сопоставление с формами редактирования // ═══════════════════════════════════════════════════════════════ settings.DetailFields = new DetailRecordFieldMap { PrimaryKeyField = "Article", // Ключ товара (readonly при редактировании) NameField = "Наименование товара", // Название CategoryField = "Категория товара", // Выпадающий список DescriptionField = "Описание товара", // Многострочное описание ManufacturerField = "Производитель", // Выпадающий список SupplierField = "Поставщик", // Выпадающий список PriceField = "Цена", // ≥ 0, не более 2 знаков после запятой UnitField = "Единица измерения", // шт., упак. и т.д. StockField = "Кол-во на складе", // Целое ≥ 0 DiscountField = "Действующая скидка", // 0–100 % ImageField = "Фото" // Имя файла изображения в БД }; settings.OrderFields = new OrderRecordFieldMap { OrderNumberField = "OrderId", // MAX+1 при добавлении, readonly при ред. ArticleField = "Артикул заказа", // Состав заказа (только просмотр/текст) StatusField = "Статус заказа", // Выпадающий список AddressField = "Адрес пункта выдачи", // ID пункта выдачи (int) OrderDateField = "Дата заказа", // DateTimePicker DeliveryDateField = "Дата доставки", // Опционально (чекбокс) ClientNameField = "ФИО авторизированного клиента", // Клиент заказа (ComboBox) PickupCodeField = "Код для получения" // Код выдачи }; // ═══════════════════════════════════════════════════════════════ // ШАГ 5. Авторизация — имена столбцов и ролей из vw_UsersLogin // ═══════════════════════════════════════════════════════════════ settings.LoginFieldName = "Логин"; // Столбец логина в DataTable settings.PasswordFieldName = "Пароль"; // Столбец пароля settings.RoleFieldName = "Роль"; // Столбец роли settings.FullNameFieldName = "ФИО"; // Отображаемое имя пользователя // Строковые значения ролей в БД → уровень доступа: settings.AdministratorRoleName = "Администратор"; // Полный CRUD каталог + заказы settings.ManagerRoleName = "Менеджер"; // Каталог с фильтром + просмотр заказов settings.ClientRoleName = "Авторизированный клиент"; // Только просмотр каталога // ═══════════════════════════════════════════════════════════════ // ШАГ 6. ApplicationDataContext — DataSet, загрузка, сохранение // ═══════════════════════════════════════════════════════════════ var data = new ApplicationDataContext { // ── DataSet и имена таблиц ────────────────────────────── CatalogDataSet = dataSet, CatalogTableName = "vCatalog", // Таблица каталога в DataSet OrdersDataSet = dataSet, // Можно один DataSet на всё приложение OrdersTableName = "vOrders", UsersDataSet = dataSet, UsersTableName = "vw_UsersLogin", // ── Загрузка данных (только Fill — Update в TableAdapter не нужен) ── LoadUsers = () => usersTableAdapter.Fill(dataSet.vw_UsersLogin), LoadCatalog = () => tovarTableAdapter.Fill(dataSet.vCatalog), LoadOrders = () => ordersTableAdapter.Fill(dataSet.vOrders), // PersistCatalogChanges / PersistOrderChanges можно не задавать — // подключатся автоматически через WithViewDataPersistence ниже } // Insert/Update/Delete для view без правки .xsd: // ViewPersistenceProfile.NormalizedCatalogView — каталог (Product + справочники) // ViewPersistenceProfile.NormalizedOrdersView — заказы ([Order] + OrderItem + справочники) .WithViewDataPersistence(connectionString, settings); // ═══════════════════════════════════════════════════════════════ // ШАГ 7. Запуск: вход → главная форма → каталог / заказы // ApplicationNavigator передаёт UsersDataSet в форму заказов // для ComboBox клиентов (роль ClientRoleName из settings) // ═══════════════════════════════════════════════════════════════ new ApplicationNavigator(settings, data).Start(); } } } ``` ### CreateCatalogCrudOptions — параметры изображений Метод `CreateCatalogCrudOptions()` возвращает `DataSetCrudOptions` с полями: - `AutoResizeImages` — масштабирование в `ScrollableDetailPanel` (также задаётся на панели через settings) - `DeleteImageFileOnRemove` — удаление файла с диска при очистке поля «Фото» - `DeleteOldImageOnReplace` — удаление предыдущего файла при замене изображения - `ConnectionString` — строка подключения для проверки связанных записей при удалении - `ImageResizeWidth` / `ImageResizeHeight` — размер сохраняемого изображения (300×200) ### TableAdapter: только Fill(), без Update в Designer Для view **не нужно** добавлять Insert/Update/Delete в `.xsd`. Сохранение выполняет `ViewDataTablePersistence` (см. `.WithViewDataPersistence()`). ### Typed DataSet: что настроить 1. Создайте Typed DataSet с view-таблицами (каталог, заказы, пользователи). 2. Укажите имена таблиц в `ApplicationDataContext`. 3. Сопоставьте столбцы через `DetailRecordFieldMap` / `OrderRecordFieldMap`. 4. Подключите `.WithViewDataPersistence(connectionString, settings)`. ## Платформы - .NET Framework 4.8 - .NET 8 (Windows)