
C# ObservableCollection (Cómo Funciona para Desarrolladores)
En C#, el ObservableCollection es una poderosa estructura de datos que notifica automáticamente a los oyentes cuando se agregan, eliminan o cambian elementos. Es particularmente útil para escenarios de colección de datos dinámicos, como cuando necesitas reflejar cambios en tiempo real en tu interfaz de usuario o informes. Cuando se combina con IronPDF, esta poderosa colección se puede usar para generar PDF dinámicos basados en datos en vivo.
IronPDF es una robusta biblioteca para generar PDF en C#. Con sus capacidades de conversión de HTML a PDF, es fácil crear PDF de alta calidad, ya sea que necesites generar facturas, informes o cualquier otro documento basado en datos en tiempo real. En este artículo, te mostraremos cómo integrar la clase ObservableCollection con IronPDF, aprovechando la vinculación de datos para generar un PDF que se actualiza dinámicamente a medida que cambian los datos.
Entendiendo ObservableCollection
¿Qué es una colección observable?
ObservableCollection es una clase en C# que implementa la interfaz INotifyCollectionChanged, que proporciona notificaciones cuando se añaden, eliminan o modifican elementos. Se usa comúnmente para la vinculación de datos en aplicaciones de interfaz de usuario como WPF, donde los cambios en la colección automáticamente generan actualizaciones en la interfaz de usuario. A diferencia de otras colecciones como List, una ObservableCollection ofrece notificaciones de eventos incorporadas, lo que la hace perfecta para escenarios donde los datos necesitan reflejarse en tiempo real.
La ObservableCollection maneja automáticamente los cambios en toda la colección, facilitando la gestión y visualización de colecciones de datos dinámicos en tu aplicación.
Casos de uso comunes
- Enlace con componentes de UI: en WPF, por ejemplo, ObservableCollection se utiliza a menudo para vincular datos a controles como ListView, DataGrid y ComboBox. Cuando la colección subyacente cambia, la interfaz de usuario se actualiza automáticamente.
- Actualizaciones en tiempo real: cuando los datos cambian con frecuencia, ObservableCollection garantiza que la interfaz de usuario esté siempre sincronizada. Por ejemplo, podrías usarlo para un informe en vivo donde se agregan nuevas entradas de datos a la colección en tiempo real y el informe se actualiza en consecuencia.
- Cambios dinámicos: si su aplicación permite a los usuarios agregar, eliminar o modificar datos, se puede utilizar ObservableCollection para reflejar automáticamente esos cambios en la interfaz de usuario u otros componentes.
Trabajar con IronPDF
Descripción general de IronPDF

Como mencionamos al inicio de este artículo, IronPDF es una biblioteca de generación de PDF en .NET que facilita la creación, modificación y renderizado de documentos PDF. A diferencia de algunas otras bibliotecas de PDF, IronPDF proporciona un conjunto rico de características que simplifican el trabajo con PDF, como convertir HTML a PDF, agregar marcas de agua, manipular PDF existentes y más.
IronPDF también permite a los desarrolladores renderizar PDF desde diferentes fuentes de datos, incluidos HTML, imágenes y texto plano, lo cual puede ser particularmente útil cuando necesitas presentar datos dinámicos. Con la API de IronPDF, puedes generar PDF de alta calidad, incluyendo diseños detallados, tablas, imágenes y estilos.
Instalación de IronPDF
Para comenzar con IronPDF, necesitas instalar la biblioteca a través de NuGet. Puedes agregarlo a tu proyecto ejecutando el siguiente comando en la Consola del Administrador de Paquetes:
Una vez instalado, puedes inicializar IronPDF y usar sus potentes características. Para este artículo, nos centraremos en generar PDF a partir de datos dinámicos en una ObservableCollection.
Integración de ObservableCollection con IronPDF
Caso de uso: Generación dinámica de PDFs a partir de ObservableCollection
Imaginemos un escenario donde necesitas generar un PDF de factura a partir de una lista de elementos almacenados en un ObservableCollection. A medida que se agregan o eliminan elementos de la colección, el PDF debería regenerarse automáticamente para reflejar el estado actual de los datos.
Para esta tarea, ObservableCollection proporciona una manera fácil de gestionar los elementos en la factura, mientras que IronPDF nos permitirá generar y exportar la factura a formato PDF.
Enlace de datos a contenido PDF
Para vincular los datos en una ObservableCollection a un PDF, necesitas recorrer la colección y agregar sus elementos al contenido del PDF. IronPDF proporciona métodos para crear tablas, agregar texto y personalizar el diseño, haciendo fácil representar los datos en un formato estructurado.
Por ejemplo, si tienes una factura con varios artículos, puedes generar el PDF dinámicamente recorriendo el ObservableCollection y agregando cada artículo a una tabla o lista en el documento. IronPDF permite un alto nivel de personalización, incluyendo el ajuste de fuentes, bordes e incluso la inclusión de imágenes como logotipos o códigos de barras.
Ejemplo uno: Generación de un PDF utilizando ObservableCollection
Veamos un ejemplo simple para demostrar cómo funciona esto. Supongamos que tienes una colección de personas (representadas por la clase Persona) y quieres generar un PDF que refleje los detalles de estas personas. Cada vez que se añade una nueva persona a la colección, el PDF se actualizará automáticamente.
Ejemplo de clase de persona
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}Public Class Person
Public Property Name() As String
Public Property Age() As Integer
End ClassEn este caso, la clase Persona contiene propiedades básicas como Nombre y Edad. Usaremos esta clase junto con el ObservableCollection para generar un PDF dinámicamente.
Creación de ObservableCollection
using System.Collections.ObjectModel;
var collection = new ObservableCollection<Person>
{
new Person { Name = "John Doe", Age = 30 },
new Person { Name = "Jane Smith", Age = 28 }
};Imports System.Collections.ObjectModel
Private collection = New ObservableCollection(Of Person) From {
New Person With {
.Name = "John Doe",
.Age = 30
},
New Person With {
.Name = "Jane Smith",
.Age = 28
}
}Esta ObservableCollection contiene una colección de objetos Persona, cada uno con un Nombre y una Edad. Cuando un elemento es agregado o eliminado, se activan manejadores de eventos, que utilizaremos para actualizar el PDF dinámicamente.
Añadir controladores de eventos para cambios de colección
En este ejemplo, nos suscribimos al evento CollectionChanged de la clase ObservableCollection para regenerar automáticamente el PDF siempre que la colección cambie. Esto es útil si necesitas responder a cambios como añadir o remover un objeto Persona.
// Subscribe to the ObservableCollection's CollectionChanged event
collection.CollectionChanged += (object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) =>
{
// Regenerate the PDF whenever the collection changes
GeneratePersonPDF(collection);
};' Subscribe to the ObservableCollection's CollectionChanged event
AddHandler collection.CollectionChanged, Sub(sender As Object, e As System.Collections.Specialized.NotifyCollectionChangedEventArgs)
' Regenerate the PDF whenever the collection changes
GeneratePersonPDF(collection)
End SubAñadir gente nueva a la colección
Puedes agregar una nueva Persona a la colección y el manejador de eventos activará la regeneración del PDF. Este enfoque maneja automáticamente los cambios en la lista completa de personas.
// Adding a new person to the collection
collection.Add(new Person { Name = "Alice Brown", Age = 32 });' Adding a new person to the collection
collection.Add(New Person With {
.Name = "Alice Brown",
.Age = 32
})Cada vez que añades una nueva persona a la colección, se regenerará el PDF, incluyendo la nueva entrada.
Propiedad de edad vinculante
También puedes vincular la propiedad edad de una Persona a algún sistema externo (como la interfaz de usuario u otras partes de la aplicación) para reflejar automáticamente los cambios.
A continuación se muestra un ejemplo de cómo se vincularía la propiedad Edad en la clase Persona:
public class Person
{
public string Name { get; set; }
private int _age;
public int Age
{
get { return _age; }
set
{
_age = value;
// Raise property changed event here if using data binding
}
}
}Public Class Person
Public Property Name() As String
Private _age As Integer
Public Property Age() As Integer
Get
Return _age
End Get
Set(ByVal value As Integer)
_age = value
' Raise property changed event here if using data binding
End Set
End Property
End ClassUso de ObservableCollection con Binding
Demostremos el uso de vinculación de edad a un elemento de la interfaz de usuario, actualizando el valor de la edad y observando cómo se reflejan los cambios en la colección:
ObservableCollection<Person> people = new ObservableCollection<Person>
{
new Person { Name = "John", Age = 30 },
new Person { Name = "Jane", Age = 28 }
};
// Binding the Age of the first person to a UI element (pseudo-code)
someUIElement.Text = people[0].Age.ToString();Dim people As New ObservableCollection(Of Person) From {
New Person With {
.Name = "John",
.Age = 30
},
New Person With {
.Name = "Jane",
.Age = 28
}
}
' Binding the Age of the first person to a UI element (pseudo-code)
someUIElement.Text = people(0).Age.ToString()Generación del PDF con IronPDF
Ahora que hemos configurado el ObservableCollection y añadido manejadores de eventos, es tiempo de enfocarnos en generar un PDF que refleje la colección dinámica de personas.
using IronPdf;
public void GeneratePersonPDF(ObservableCollection<Person> people)
{
var pdf = new ChromePdfRenderer(); // Initialize IronPDF's ChromePdfRenderer class
// Create HTML content representing the people in the collection
var htmlContent = "<h1>People Information</h1><table border='1' cellpadding='5' cellspacing='0'>" +
"<tr><th>Name</th><th>Age</th></tr>";
foreach (var person in people)
{
htmlContent += $"<tr><td>{person.Name}</td><td>{person.Age}</td></tr>";
}
htmlContent += "</table>";
// Convert the HTML content to a PDF
var pdfDocument = pdf.RenderHtmlAsPdf(htmlContent);
// Save the generated PDF to disk
pdfDocument.SaveAs("PeopleInformation.pdf");
}Imports IronPdf
Public Sub GeneratePersonPDF(people As ObservableCollection(Of Person))
Dim pdf = New ChromePdfRenderer() ' Initialize IronPDF's ChromePdfRenderer class
' Create HTML content representing the people in the collection
Dim htmlContent = "<h1>People Information</h1><table border='1' cellpadding='5' cellspacing='0'>" &
"<tr><th>Name</th><th>Age</th></tr>"
For Each person In people
htmlContent += $"<tr><td>{person.Name}</td><td>{person.Age}</td></tr>"
Next
htmlContent += "</table>"
' Convert the HTML content to a PDF
Dim pdfDocument = pdf.RenderHtmlAsPdf(htmlContent)
' Save the generated PDF to disk
pdfDocument.SaveAs("PeopleInformation.pdf")
End SubEjemplo dos: generación de una factura PDF a partir de ObservableCollection
Aquí hay un ejemplo de cómo generar un PDF desde un ObservableCollection de artículos de factura usando IronPDF:
Paso 1: Ejemplo de clase de artículo de factura
Esta clase representa un artículo en la factura, con propiedades para el nombre del artículo, cantidad, precio y precio total.
public class InvoiceItem
{
public string ItemName { get; set; }
public int Quantity { get; set; }
public decimal Price { get; set; }
public decimal Total => Quantity * Price;
}Public Class InvoiceItem
Public Property ItemName() As String
Public Property Quantity() As Integer
Public Property Price() As Decimal
Public ReadOnly Property Total() As Decimal
Get
Return Quantity * Price
End Get
End Property
End ClassPaso 2: Ejemplo de ObservableCollection
Este ejemplo inicializa una ObservableCollection que contiene varios artículos de factura. Puedes agregar, eliminar o modificar dinámicamente los artículos en esta colección.
ObservableCollection<InvoiceItem> invoiceItems = new ObservableCollection<InvoiceItem>
{
new InvoiceItem { ItemName = "Item 1", Quantity = 2, Price = 10.00m },
new InvoiceItem { ItemName = "Item 2", Quantity = 1, Price = 25.00m },
new InvoiceItem { ItemName = "Item 3", Quantity = 5, Price = 5.00m }
};Dim invoiceItems As New ObservableCollection(Of InvoiceItem) From {
New InvoiceItem With {
.ItemName = "Item 1",
.Quantity = 2,
.Price = 10.00D
},
New InvoiceItem With {
.ItemName = "Item 2",
.Quantity = 1,
.Price = 25.00D
},
New InvoiceItem With {
.ItemName = "Item 3",
.Quantity = 5,
.Price = 5.00D
}
}Paso 3: Generar el PDF con IronPDF
Aquí, creamos una función para generar el PDF. Esta función utiliza los datos en el ObservableCollection y los convierte a HTML, que luego se renderiza como un PDF usando IronPDF.
public void GenerateInvoicePDF(ObservableCollection<InvoiceItem> items)
{
var pdf = new ChromePdfRenderer(); // Initialize IronPDF's ChromePdfRenderer class
// Create HTML content representing the invoice
var htmlContent = "<h1>Invoice</h1><table border='1' cellpadding='5' cellspacing='0'>" +
"<tr><th>Item</th><th>Quantity</th><th>Price</th><th>Total</th></tr>";
foreach (var item in items)
{
htmlContent += $"<tr><td>{item.ItemName}</td><td>{item.Quantity}</td><td>{item.Price:C}</td><td>{item.Total:C}</td></tr>";
}
htmlContent += "</table>";
// Convert the HTML content to a PDF
var pdfDocument = pdf.RenderHtmlAsPdf(htmlContent);
// Save the generated PDF to disk
pdfDocument.SaveAs("Invoice.pdf");
}Public Sub GenerateInvoicePDF(ByVal items As ObservableCollection(Of InvoiceItem))
Dim pdf = New ChromePdfRenderer() ' Initialize IronPDF's ChromePdfRenderer class
' Create HTML content representing the invoice
Dim htmlContent = "<h1>Invoice</h1><table border='1' cellpadding='5' cellspacing='0'>" & "<tr><th>Item</th><th>Quantity</th><th>Price</th><th>Total</th></tr>"
For Each item In items
htmlContent &= $"<tr><td>{item.ItemName}</td><td>{item.Quantity}</td><td>{item.Price:C}</td><td>{item.Total:C}</td></tr>"
Next item
htmlContent &= "</table>"
' Convert the HTML content to a PDF
Dim pdfDocument = pdf.RenderHtmlAsPdf(htmlContent)
' Save the generated PDF to disk
pdfDocument.SaveAs("Invoice.pdf")
End SubPaso 4: Suscribirse al evento CollectionChanged
Debido a que ObservableCollection notifica automáticamente los cambios, puedes regenerar fácilmente el PDF siempre que la colección se actualice. Por ejemplo, si se agrega o elimina un artículo, el PDF se puede regenerar con los datos actualizados.
Aquí te mostramos cómo puedes suscribirte al evento CollectionChanged y regenerar el PDF siempre que la colección cambie:
// Subscribe to the ObservableCollection's CollectionChanged event
invoiceItems.CollectionChanged += (sender, e) =>
{
// Regenerate the PDF whenever the collection changes
GenerateInvoicePDF(invoiceItems);
};' Subscribe to the ObservableCollection's CollectionChanged event
AddHandler invoiceItems.CollectionChanged, Sub(sender, e)
' Regenerate the PDF whenever the collection changes
GenerateInvoicePDF(invoiceItems)
End SubPaso 5: Añadir elementos y probar
Ahora puedes probar agregando nuevos artículos a la ObservableCollection y observando cómo se regenera automáticamente el PDF.
// Adding a new item to the ObservableCollection
invoiceItems.Add(new InvoiceItem { ItemName = "Item 4", Quantity = 3, Price = 12.50m });' Adding a new item to the ObservableCollection
invoiceItems.Add(New InvoiceItem With {
.ItemName = "Item 4",
.Quantity = 3,
.Price = 12.50D
})Ejemplo de código completo
using System;
using System.Collections.ObjectModel;
using IronPdf;
public class InvoiceItem
{
public string ItemName { get; set; }
public int Quantity { get; set; }
public decimal Price { get; set; }
// Property to calculate the total price for each item
public decimal Total => Quantity * Price;
}
public class InvoiceGenerator
{
// Function to generate the invoice PDF
public void GenerateInvoicePDF(ObservableCollection<InvoiceItem> items)
{
var pdf = new ChromePdfRenderer(); // Initialize IronPDF's ChromePdfRenderer class
// Create HTML content representing the invoice
var htmlContent = "<h1>Invoice</h1><table border='1' cellpadding='5' cellspacing='0'>" +
"<tr><th>Item</th><th>Quantity</th><th>Price</th><th>Total</th></tr>";
foreach (var item in items)
{
htmlContent += $"<tr><td>{item.ItemName}</td><td>{item.Quantity}</td><td>{item.Price:C}</td><td>{item.Total:C}</td></tr>";
}
htmlContent += "</table>";
// Convert the HTML content to a PDF
var pdfDocument = pdf.RenderHtmlAsPdf(htmlContent);
// Save the generated PDF to disk
pdfDocument.SaveAs("Invoice.pdf");
}
// Main function to test the code
public static void Main(string[] args)
{
var invoiceItems = new ObservableCollection<InvoiceItem>
{
new InvoiceItem { ItemName = "Item 1", Quantity = 2, Price = 10.00m },
new InvoiceItem { ItemName = "Item 2", Quantity = 1, Price = 25.00m },
new InvoiceItem { ItemName = "Item 3", Quantity = 5, Price = 5.00m }
};
var invoiceGenerator = new InvoiceGenerator();
// Subscribe to the ObservableCollection's CollectionChanged event
invoiceItems.CollectionChanged += (sender, e) =>
{
// Regenerate the PDF whenever the collection changes
invoiceGenerator.GenerateInvoicePDF(invoiceItems);
};
// Generate initial PDF
invoiceGenerator.GenerateInvoicePDF(invoiceItems);
// Add a new item to the collection and automatically regenerate the PDF
invoiceItems.Add(new InvoiceItem { ItemName = "Item 4", Quantity = 3, Price = 12.50m });
// Remove an item and see the PDF update
invoiceItems.RemoveAt(0);
}
}Imports System
Imports System.Collections.ObjectModel
Imports IronPdf
Public Class InvoiceItem
Public Property ItemName As String
Public Property Quantity As Integer
Public Property Price As Decimal
' Property to calculate the total price for each item
Public ReadOnly Property Total As Decimal
Get
Return Quantity * Price
End Get
End Property
End Class
Public Class InvoiceGenerator
' Function to generate the invoice PDF
Public Sub GenerateInvoicePDF(items As ObservableCollection(Of InvoiceItem))
Dim pdf = New ChromePdfRenderer() ' Initialize IronPDF's ChromePdfRenderer class
' Create HTML content representing the invoice
Dim htmlContent = "<h1>Invoice</h1><table border='1' cellpadding='5' cellspacing='0'>" &
"<tr><th>Item</th><th>Quantity</th><th>Price</th><th>Total</th></tr>"
For Each item In items
htmlContent &= $"<tr><td>{item.ItemName}</td><td>{item.Quantity}</td><td>{item.Price:C}</td><td>{item.Total:C}</td></tr>"
Next
htmlContent &= "</table>"
' Convert the HTML content to a PDF
Dim pdfDocument = pdf.RenderHtmlAsPdf(htmlContent)
' Save the generated PDF to disk
pdfDocument.SaveAs("Invoice.pdf")
End Sub
' Main function to test the code
Public Shared Sub Main(args As String())
Dim invoiceItems = New ObservableCollection(Of InvoiceItem) From {
New InvoiceItem With {.ItemName = "Item 1", .Quantity = 2, .Price = 10.0D},
New InvoiceItem With {.ItemName = "Item 2", .Quantity = 1, .Price = 25.0D},
New InvoiceItem With {.ItemName = "Item 3", .Quantity = 5, .Price = 5.0D}
}
Dim invoiceGenerator = New InvoiceGenerator()
' Subscribe to the ObservableCollection's CollectionChanged event
AddHandler invoiceItems.CollectionChanged, Sub(sender, e)
' Regenerate the PDF whenever the collection changes
invoiceGenerator.GenerateInvoicePDF(invoiceItems)
End Sub
' Generate initial PDF
invoiceGenerator.GenerateInvoicePDF(invoiceItems)
' Add a new item to the collection and automatically regenerate the PDF
invoiceItems.Add(New InvoiceItem With {.ItemName = "Item 4", .Quantity = 3, .Price = 12.5D})
' Remove an item and see the PDF update
invoiceItems.RemoveAt(0)
End Sub
End ClassSalida

Qué hace el código
- Clase InvoiceItem: representa un elemento de factura con propiedades para ItemName, Cantidad, Precio y un Total calculado.
- ObservableCollection: se utiliza para almacenar la lista de elementos de la factura. La colección notifica automáticamente a los oyentes de cualquier cambio (por ejemplo, cuando se agregan o se eliminan artículos).
- GenerateInvoicePDF: Este método crea el contenido HTML que representa la factura y utiliza IronPDF para convertirlo a PDF.
- CollectionChanged: el evento ObservableCollection se maneja para regenerar el PDF cada vez que la colección cambia, lo que hace que la generación del PDF sea dinámica.
- Prueba: El método principal demuestra cómo agregar y eliminar elementos de ObservableCollection desencadena la regeneración de PDF.
Consideraciones sobre el rendimiento
Gestión de grandes colecciones
Cuando se trabaja con instancias grandes de ObservableCollection, el rendimiento puede convertirse en una preocupación. Regenerar un PDF cada vez que cambia la colección podría ser intensivo en recursos si hay una gran cantidad de artículos. Para mitigar esto, considera agrupar actualizaciones o usar técnicas como la paginación para evitar sobrecargar el proceso de generación de PDF.
Reproducción eficaz de PDF
Para asegurar que el renderizado de PDF sea eficiente, ten en cuenta los siguientes consejos:
- Minimizar re-renderizados innecesarios: Solo regenerar el PDF cuando los datos cambien significativamente (por ejemplo, cuando se agreguen o eliminen artículos).
- Optimizar el diseño de la tabla: Al renderizar grandes conjuntos de datos, divídelos en secciones más pequeñas y manejables para mejorar el tiempo de renderizado.
- Usar caché: Cachear PDF previamente generados para datos estáticos o que cambian con poca frecuencia.
Conclusión
Combinando el ObservableCollection de C# con IronPDF, puedes generar fácilmente PDF dinámicos que reflejan cambios en tiempo real en los datos de tu aplicación. Ya sea que estés generando facturas, informes u otros documentos, este enfoque permite actualizar automáticamente el contenido del PDF cada vez que la colección subyacente cambia.
La integración de ObservableCollection asegura que tu aplicación esté siempre actualizada con un esfuerzo mínimo, mientras que IronPDF maneja la labor de renderizar PDF de alta calidad. Siguiendo las mejores prácticas y consejos de rendimiento discutidos en este artículo, puedes crear una experiencia de generación de PDF optimizada para tus aplicaciones .NET.
¿Quieres probar IronPDF tú mismo? Descarga la prueba gratuita hoy para elevar tus proyectos de PDF en C#, y asegúrate de consultar la sección de documentación extensa para ver más de esta biblioteca en acción.

Jacob Mellor es Director de Tecnología de Iron Software y un ingeniero visionario pionero en la tecnología C# PDF. Como desarrollador original de la base de código principal de Iron Software, ha dado forma a la arquitectura de productos de la empresa desde su creación, transformándola, junto con el director ejecutivo Cameron Rimington, en una empresa de más de 50 personas que presta servicios a la NASA, Tesla y organismos gubernamentales de todo el mundo.
Artículos Relacionados


