|
|
hace 1 mes | |
|---|---|---|
| .. | ||
| lib | hace 1 mes | |
| .signature.p7s | hace 1 mes | |
| AlfaToad.DataSetCRUDS.1.1.7.nupkg | hace 1 mes | |
| README.md | hace 1 mes | |
NuGet-пакет готовых форм добавления и редактирования для контролов AlfaToad.CustomControls.
Достаточно указать DataSet, имя таблицы и делегат сохранения — CRUD для ScrollableDetailPanel и ScrollableOrderPanel работает автоматически.
| Компонент | Назначение |
|---|---|
DetailRecordEditForm |
Модальная форма добавления/редактирования записи каталога |
OrderRecordEditForm |
Модальная форма добавления/редактирования записи заказа |
DetailPanelCrudBinder |
Подключает ScrollableDetailPanel к форме и сохранению |
OrderPanelCrudBinder |
Подключает ScrollableOrderPanel к форме и сохранению |
DataSetCrudHost |
Единая точка настройки обеих панелей |
DetailRecordFieldMap |
Сопоставление имён столбцов каталога |
OrderRecordFieldMap |
Сопоставление имён столбцов заказов |
DataSetCrudOptions |
Оформление, папка изображений, ресайз фото, ConnectionString, ClientUsersTable, валидация удаления, сохранение |
AppDialog |
Единые окна: ошибка / предупреждение / информация / подтверждение |
ViewDataTablePersistence |
Insert/Update/Delete для view без TableAdapter.Update |
ViewPersistenceProfile |
Профиль SQL: NormalizedCatalogView, NormalizedOrdersView |
Designer.cs)AppearancePalette из CustomControlsImagesFolderDropDownList с placeholder «— выберите —» для категории, производителя, поставщика, единицы измерения, статуса и клиента заказаRecordAddRequested, RecordEditRequested, RecordDeletedEndEditSession() после закрытия формыRefreshRows() после сохраненияPersistChangesdotnet add package AlfaToad.DataSetCRUDS --version 1.0.5
<PackageReference Include="AlfaToad.DataSetCRUDS" Version="1.0.5" />
Зависимость: AlfaToad.CustomControls ≥ 4.2.4
Visual Studio не генерирует Update() для представлений (DbObjectType="View").
Пакет решает это на уровне NuGet: достаточно создать Typed DataSet с одним view и использовать только Fill().
using AlfaToad.DataSetCRUDS.Configuration;
using AlfaToad.DataSetCRUDS.Persistence;
// DataSet с view каталога — только Fill(), Update() в TableAdapter не нужен
// ViewPersistenceProfile.NormalizedCatalogView — INSERT/UPDATE/DELETE в Product + справочники
var persistCatalog = ViewDataTablePersistence.CreatePersistAction(
dataSet,
"vCatalog",
connectionString,
ViewPersistenceProfile.NormalizedCatalogView,
settings.DetailFields);
DetailPanelCrudBinder.WireUp(panel, dataSet, "vCatalog", persistCatalog, settings.DetailFields);
Для заказов:
// ViewPersistenceProfile.NormalizedOrdersView — INSERT/UPDATE/DELETE в dbo.[Order] + OrderItem;
// ClientUserId передаётся параметром @ClientUserId (поиск по FullName в dbo.[User])
var persistOrders = ViewDataTablePersistence.CreatePersistAction(
dataSet,
"vOrders",
connectionString,
ViewPersistenceProfile.NormalizedOrdersView,
orderFields: settings.OrderFields);
ViewDataTablePersistence.ApplyChanges выполняет INSERT/UPDATE/DELETE в таблицы Product / [Order] / OrderItem,
переводя текстовые поля view (Поставщик, Категория, Статус…) в ID справочников.
С AlfaToad.DefaultScreens — одна строка:
var data = new ApplicationDataContext { /* DataSet, Fill-делегаты */ }
.WithViewDataPersistence(connectionString, settings);
Ручное редактирование .xsd не требуется.
Program.csСм. также AlfaToad.DefaultScreens README — ниже шаблон с комментариями к полям пакета:
using System;
using System.Drawing;
using System.Windows.Forms;
using AlfaToad.CustomControls.Theme;
using AlfaToad.DataSetCRUDS.Configuration;
using AlfaToad.DefaultScreens.Configuration;
using AlfaToad.DefaultScreens.Navigation;
using YourApp; // ваш Typed DataSet
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 YourDataSet(); // замените на ваш Typed DataSet
var tovarTableAdapter = new vCatalogTableAdapter();
var ordersTableAdapter = new vOrdersTableAdapter();
var usersTableAdapter = new vw_UsersLoginTableAdapter();
var connectionString = "Server=YOUR_SERVER;Database=YOUR_DATABASE;Trusted_Connection=True;";
// ═══════════════════════════════════════════════════════════════
// ШАГ 2. ApplicationScreenSettings
// ═══════════════════════════════════════════════════════════════
var settings = ApplicationScreenSettings.CreateDefault();
settings.BackMenuText = "Назад";
settings.ImagesFolder = @"C:\Path\To\Your\Resources\import";
settings.ImageResizeWidth = 300;
settings.ImageResizeHeight = 200;
settings.ApplyResourcePaths();
// CreateCatalogCrudOptions() задаёт AutoResizeImages, DeleteImageFileOnRemove,
// DeleteOldImageOnReplace, ConnectionString, ImageResizeWidth/Height
// CreateOrderCrudOptions(clientUsers, connectionString) — ClientUsersTable для ComboBox клиента
settings.DetailFields = new DetailRecordFieldMap { /* столбцы каталога */ };
settings.OrderFields = new OrderRecordFieldMap
{
ClientNameField = "ФИО авторизированного клиента" // ComboBox на форме заказа
};
// ═══════════════════════════════════════════════════════════════
// ШАГ 6. ApplicationDataContext + WithViewDataPersistence
// ViewPersistenceProfile.NormalizedCatalogView / NormalizedOrdersView
// ═══════════════════════════════════════════════════════════════
var data = new ApplicationDataContext
{
CatalogDataSet = dataSet,
CatalogTableName = "vCatalog",
OrdersDataSet = dataSet,
OrdersTableName = "vOrders",
UsersDataSet = dataSet,
UsersTableName = "vw_UsersLogin",
LoadUsers = () => usersTableAdapter.Fill(dataSet.vw_UsersLogin),
LoadCatalog = () => tovarTableAdapter.Fill(dataSet.vCatalog),
LoadOrders = () => ordersTableAdapter.Fill(dataSet.vOrders),
}
.WithViewDataPersistence(connectionString, settings);
new ApplicationNavigator(settings, data).Start();
}
}
}
using AlfaToad.CustomControls.Controls;
using AlfaToad.DataSetCRUDS.Integration;
var panel = new ScrollableDetailPanel { Dock = DockStyle.Fill };
panel.AllowAdd = panel.AllowEdit = panel.AllowDelete = true;
DetailPanelCrudBinder.WireUp(
panel,
catalogDataSet,
"CatalogItems",
() => catalogTableAdapter.Update(catalogDataSet),
options: new DataSetCrudOptions
{
ImagesFolder = @"C:\Path\To\Your\Resources\images",
AutoResizeImages = true,
DeleteImageFileOnRemove = true,
DeleteOldImageOnReplace = true,
ConnectionString = connectionString,
ImageResizeWidth = 300,
ImageResizeHeight = 200,
PersistChanges = () => catalogTableAdapter.Update(catalogDataSet)
});
using AlfaToad.DataSetCRUDS.Integration;
OrderPanelCrudBinder.WireUp(
ordersPanel,
ordersDataSet,
"Orders",
() => ordersTableAdapter.Update(ordersDataSet),
orderFields,
new DataSetCrudOptions
{
ClientUsersTable = clientUsersTable, // UserId + FullName, роль = Client
DefaultClientName = "Иванов Иван Иванович",
ConnectionString = connectionString
});
new DataSetCrudHost()
.WireDetailPanel(detailPanel, catalogDataSet, "CatalogItems", () => taCatalog.Update(catalogDataSet))
.WireOrderPanel(orderPanel, ordersDataSet, "Orders", () => taOrders.Update(ordersDataSet));
Если ваши столбцы в БД имеют другие имена, задайте карту полей:
var fields = new DetailRecordFieldMap
{
PrimaryKeyField = "Article",
NameField = "Наименование товара",
CategoryField = "Категория товара",
ImageField = "Фото",
PriceField = "Цена",
StockField = "Кол-во на складе",
DiscountField = "Действующая скидка"
};
DetailPanelCrudBinder.WireUp(panel, dataSet, "vCatalog", persist, fields);
var options = new DataSetCrudOptions
{
ValidateBeforeSave = row =>
{
var key = row["RecordId"]?.ToString();
return IsUsedInOrders(key) ? "Запись используется в связанных данных." : null;
},
PersistChanges = () => tableAdapter.Update(dataSet)
};
var binder = new DetailPanelCrudBinder(panel)
.Configure(dataSet, "CatalogItems", () => ta.Update(dataSet))
.Attach();
// При закрытии формы:
binder.Detach();