EvolutivaWinformsUtils 1.0.0
dotnet add package EvolutivaWinformsUtils --version 1.0.0
NuGet\Install-Package EvolutivaWinformsUtils -Version 1.0.0
<PackageReference Include="EvolutivaWinformsUtils" Version="1.0.0" />
<PackageVersion Include="EvolutivaWinformsUtils" Version="1.0.0" />
<PackageReference Include="EvolutivaWinformsUtils" />
paket add EvolutivaWinformsUtils --version 1.0.0
#r "nuget: EvolutivaWinformsUtils, 1.0.0"
#:package EvolutivaWinformsUtils@1.0.0
#addin nuget:?package=EvolutivaWinformsUtils&version=1.0.0
#tool nuget:?package=EvolutivaWinformsUtils&version=1.0.0
EvolutivaWinformsUtils
Controles y utilidades reutilizables para aplicaciones Windows Forms.
La solución compila para .NET Framework 4.8 y .NET 10 Windows.
NumericTextBox
Control numérico para valores enteros y decimales.
using EvolutivaWinformsUtils.Controls.NumericTextBox;
numericTextBox.NumericType = NumericTextBoxType.Decimal;
numericTextBox.DecimalPlaces = 2;
numericTextBox.Minimum = 0;
numericTextBox.Maximum = 10000;
numericTextBox.Value = 1234.56m;
La validación no bloquea el cambio de foco. Los valores inválidos se indican
visualmente y mediante ErrorProvider.
EvolutivaDataGridView
DataGridView con una configuración visual y de comportamiento adecuada para
grillas de consulta:
- Double buffering habilitado.
- Solo lectura por defecto.
- Sin fila automática para nuevos registros.
- Sin encabezados de fila.
- Sin borde.
- Selección por celda.
- Copiado incluyendo encabezados.
- Encabezados centrados.
- Filas de 26 píxeles.
using EvolutivaWinformsUtils.Controls.DataGridView;
var grid = new EvolutivaDataGridView();
grid.ConfigureGrid<Movimiento>(ColumnDefinitions.New()
.Hidden("Id")
.DateTime("Fecha", "Fecha")
.String("Descripcion", "Descripción").Fill()
.Integer("Cantidad")
.Decimal("Importe"));
grid.DataSource = movimientos;
La grilla puede mostrar un totalizador integrado en su parte inferior. La
propiedad ShowTotalizer controla su visibilidad y SumColumnName indica la
columna numérica que se debe sumar. El totalizador muestra seleccionados / totales tanto para registros como para la suma:
grid.ShowTotalizer = true;
grid.SumColumnName = "Importe";
grid.TotalizerNumberFormat = "N2";
La selección se calcula sobre las filas que tienen al menos una celda seleccionada y se actualiza automáticamente al cambiar la selección o el contenido de la grilla.
Proyecto de ejemplo
Samples muestra el uso de:
NumericTextBox.EvolutivaDataGridView.ColumnDefinitionsyConfigureGrid.
El CRUD de la grilla utiliza MySQL de forma persistente. La cadena de conexión
del proyecto de prueba se configura en
Samples/appsettings.Development.json, que está excluido de Git:
{
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Port=3306;Database=analytics;User ID=datalink;Password=change-me;"
}
}
Luego ejecute:
dotnet run --project .\Samples\Samples.csproj
El ejemplo utiliza las tablas existentes products y orders de la base
analytics; no modifica el esquema al iniciar. El script de referencia
Samples/Database/Scripts/001_CreateProductsAndOrders.sql
contiene el esquema y los datos iniciales compartidos.
La grilla consulta productos, muestra el precio y la cantidad de órdenes
asociadas; el totalizador suma la columna Price. La muestra también incluye
los formularios y botones necesarios para extender el ejemplo con operaciones
de alta, edición y eliminación mediante el repositorio.
Si la base ya tenía creadas las tablas sin la columna price, ejecute una vez
Samples/Database/Scripts/002_AddPriceToProducts.sql antes de consultar.
SearchLookup
SearchLookup es un control WinForms para buscar y seleccionar registros de
una colección sin desplegar toda la lista como un ComboBox. Está disponible
en el namespace:
using EvolutivaWinformsUtils.Controls.SearchLookup;
El paquete unificado se instala con:
dotnet add package EvolutivaWinformsUtils
Publicación en NuGet.org
La publicación se realiza mediante GitHub Actions y Trusted Publishing con
OIDC. El workflow se ejecuta al crear un tag con formato v*:
git tag v1.0.0
git push origin v1.0.0
En NuGet.org se debe crear una política de Trusted Publishing para:
- Owner:
toledomatias - Repository:
EvolutivaWinformsUtils - Workflow file:
publish.yml - Environment: dejar vacío
La versión publicada debe coincidir con la propiedad Version del proyecto.
Ejemplo básico:
var lookup = new SearchLookup
{
DataSource = tiposIva,
ValueMember = "Codigo",
DisplayMember = "Descripcion",
SearchMembers = new[] { "Codigo", "Descripcion" },
MaxResults = 30
};
lookup.SelectedValueChanged += (_, _) =>
{
var tipo = (TipoIva?)lookup.SelectedItem;
// Usar tipo seleccionado.
};
Las propiedades AdditionalMembers y AdditionalHeaders permiten mostrar
columnas adicionales en el resultado. ShowValueColumn permite ocultar la
columna de código cuando la selección se realiza únicamente por descripción.
La búsqueda se realiza en tiempo real y admite navegación con ↑, ↓,
Enter y Escape.
SqlHelper
SqlHelper simplifica el acceso a tablas mediante mappings fluent, consultas
con Dapper y repositorios reutilizables. Sus tipos están disponibles en el
namespace:
using EvolutivaWinformsUtils.Persistence.SqlHelper;
Configuración de mappings
MappingRegistry es el punto de entrada para definir y registrar las tablas.
Si no se indica el nombre físico de una tabla, se utiliza el nombre de la
clase convertido a snake_case. Los nombres de columnas también se deducen
automáticamente convirtiendo PascalCase a snake_case, aunque pueden indicarse
explícitamente.
var mappings = new MappingRegistry()
.AddTable<Department>() // usa "department"
.AutoIncrementKey(x => x.Id)
.Field(x => x.Name)
.AddTable<Category>("categories")
.AutoIncrementKey(x => x.Id)
.Field(x => x.Name)
.Field(x => x.DepartmentId)
.ForeignKey<Department>()
.AddTable<Product>("products")
.AutoIncrementKey(x => x.Id)
.Field(x => x.Name)
.Field(x => x.Price)
.Field(x => x.Active)
.Field(x => x.CategoryId)
.ForeignKey<Category>()
.Calculated(x => x.OrderCount,
"(SELECT COUNT(*) FROM orders o WHERE o.product_id = @Prefijo.id)");
Cada foreign key se representa en la entidad mediante el campo escalar y la propiedad de navegación:
public class Category
{
public int Id { get; set; }
public string Name { get; set; } = "";
public int DepartmentId { get; set; }
public Department Department { get; set; } = null!;
}
Inyección de dependencias
El registry, la fábrica de conexiones y el repositorio pueden registrarse en el contenedor de dependencias:
services.AddSingleton(mappings);
services.AddSingleton<IConnectionFactory>(
new ConnectionFactory(connectionString, () => new MySqlConnection()));
services.AddTransient<Repository<Product>>();
El repositorio recibe el mapping centralizado y la fábrica de conexiones:
public class ProductsForm : Form
{
private readonly Repository<Product> repository;
public ProductsForm(Repository<Product> repository)
{
InitializeComponent();
this.repository = repository;
}
}
Consultas, filtros y relaciones
Las consultas se construyen encadenando filtros, ordenamientos y joins. Los
tipos de las entidades relacionadas se infieren desde los mappings, por lo que
ToList() no necesita recibir tipos genéricos adicionales.
var products = repository.Query("p")
.AddJoin("p", "category_id", "c")
.AddJoin("c", "department_id", "d")
.Where("p.active = @Activo", new { Activo = true })
.OrderBy("p.name ASC")
.ToList();
La materialización automática asigna las propiedades navegacionales:
Product
└── Category
└── Department
La misma operación está disponible de forma asíncrona mediante
ToListAsync().
Campos calculados
Los campos calculados no se incluyen por defecto. Esto evita ejecutar
innecesariamente subconsultas costosas como COUNT o SUM.
var products = repository.Query("p")
.IncludeCalculated(x => x.OrderCount)
.OrderBy("p.name ASC")
.ToList();
Solo se ejecutan los cálculos solicitados explícitamente mediante
IncludeCalculated(...).
CRUD
var product = new Product
{
Name = "Monitor",
Price = 250.00m,
Active = true,
CategoryId = 2
};
repository.Insert(product);
// product.Id contiene la clave generada por la base de datos.
product.Price = 275.00m;
repository.Update(product);
repository.Delete(product);
También existen las operaciones InsertAsync, UpdateAsync, DeleteAsync y
GetByIdAsync.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0-windows7.0 is compatible. |
| .NET Framework | net48 is compatible. net481 was computed. |
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 82 | 9/10/2026 |