Skip to main content
AppAdministrativa is a single-project WPF desktop application built on .NET 8. It follows a lightweight MVVM-inspired pattern where each module is a self-contained Page with code-behind handling both UI logic and data operations.

High-level architecture

The application does not use a full MVVM framework. Instead it adopts a MVVM-lite style:
  • View — XAML pages and dialogs define the UI and use {Binding} expressions.
  • Model — Plain C# classes (e.g., Profesor, FilaAula) declared inside each page’s code-behind file.
  • Controller logic in code-behind — Each Page class handles data loading, CRUD operations, and navigation events directly. There are no separate ViewModel classes.
This approach keeps the codebase small and easy to navigate for a single-developer project.

Single solution

AppAdministrativa.sln contains one project. All XAML pages, dialogs, models, and assets live in the same project root.

SQLite data store

Schedule data is persisted in horarios.db via System.Data.SQLite.EF6. All other modules use in-memory ObservableCollection<T> that is seeded with sample data at startup.

Application startup flow

  1. App.xaml sets StartupUri to MainWindow.xaml, which is the login screen.
  2. MainWindow authenticates the user with a photo-image login mechanism. On success it opens MenuPrincipal.
  3. MenuPrincipal is the application shell. It contains a collapsible sidebar and an inner Frame control named FrameSecundario.
  4. Each sidebar menu item navigates FrameSecundario to the corresponding module Page.
Navigation is frame-based. MenuPrincipal.xaml hosts a Frame element:
<!-- MenuPrincipal.xaml (simplified) -->
<Frame x:Name="FrameSecundario" />
Each menu click handler navigates the frame to a new page instance:
// MenuPrincipal.xaml.cs
private void Menu_Profesores_Click(object sender, MouseButtonEventArgs e)
{
    FrameSecundario.Navigate(new Profesores());
    ActualizarSeleccion(BtnMenuProfesores);
}
The active menu item is highlighted and the sidebar collapses to icon-only width:
private void ActualizarSeleccion(Border botonSeleccionado)
{
    ResetearColoresMenu();
    botonSeleccionado.Background =
        new SolidColorBrush((Color)ColorConverter.ConvertFromString("#678EC2"));
    BarraLateral.Width = 60;
}
The sidebar expands to full width (200 px) on mouse enter and collapses back to 60 px on mouse leave:
private void Menu_MouseEnter(object sender, MouseEventArgs e) { BarraLateral.Width = 200; }
private void Menu_MouseLeave(object sender, MouseEventArgs e) { BarraLateral.Width = 60; }

Module structure

Every management module follows the same two-file pattern:
FilePurpose
MyModule.xaml / .csPage with a DataGrid, search filter, and Add / Edit / Delete buttons
AgregarMyModuleWindow.xaml / .csModal Window dialog for creating and editing a single record
The module page owns the ObservableCollection<T> that backs the DataGrid. The dialog exposes a NuevoItem property that the page reads after ShowDialog() returns.
The Camaras module is an exception — it does not have an Agregar*Window dialog because cameras are monitored, not manually created.

Data layer

In-memory collections

Most modules store their data in an ObservableCollection<T> declared in code-behind. Data is seeded via a CargarDatosDePrueba() method called from the page constructor:
// Profesores.xaml.cs
ObservableCollection<Profesor> datosProfesores;

public Profesores()
{
    InitializeComponent();
    CargarDatosDePrueba();
}

private void CargarDatosDePrueba()
{
    datosProfesores = new ObservableCollection<Profesor>
    {
        new Profesor { Clave = "01", Nombre = "PUENTE MONTEJANO CESAR AUGUSTO",
                       Estudios = "Maestría en Sistemas", Investigaciones = "IA en la educación",
                       Fotografia = "foto_puente.jpg", Audio = "audio_puente.mp3" },
        // ... additional records
    };
    TablaProfesores.ItemsSource = datosProfesores;
}

SQLite (schedules)

The Horarios module persists schedule records in horarios.db using System.Data.SQLite.EF6. The database file is included in the project and configured to copy to the output directory on every build:
<!-- AppAdministrativa.csproj -->
<None Update="horarios.db">
  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
Because only horarios.db uses SQLite, you can add persistence to other modules by following the same pattern: add a table to the database and replace the ObservableCollection seed with a database query.

UI pattern

  • All layouts are defined in XAML. Code-behind does not construct UI elements programmatically except for color changes on the sidebar.
  • DataGrid controls use ItemsSource binding to an ObservableCollection<T>. Because ObservableCollection<T> raises change notifications, adding or removing items automatically refreshes the grid.
  • Modal dialogs use ShowDialog() and return data through a public property on the dialog class.
  • Search / filter logic runs on TextChanged events by iterating the collection and applying DataGrid.Items.Filter.

Dependencies

PackageVersionPurpose
.NET 8 (net8.0-windows)8.xRuntime and WPF framework
SQLitePCLRaw.core3.0.2Low-level SQLite bindings
System.Data.SQLite.EF62.0.3ADO.NET / EF6 provider for SQLite
System.Data.SQLite.EF6 targets the EF6 API, not EF Core. Do not add EF Core packages — they conflict with this provider.

Build docs developers (and LLMs) love