This sample application shows how to structure a WPF project using MVVM along with Dependency Injection in .NET 8. The app itself is a simple task manager for creating and managing tasks, but the real goal is to demonstrate clean architecture and maintainable project structure. This mini project is for mainly learning purpose. Project is documented using AI.
The solution follows a clean MVVM structure:
- Models – data structures
- ViewModels – presentation logic, state, commands
- Views – XAML UI with minimal code-behind
DI is configured using Microsoft.Extensions.DependencyInjection, similar to ASP.NET Core. All ViewModels and services are created and injected through the DI container in App.xaml.cs.
Includes examples of:
INotifyPropertyChangedObservableCollection<T>- Commands (
ICommand) - DataTemplates that map ViewModels to Views
Implemented via:
INavigationService- A
ContentControlinMainWindow - ViewModel-first navigation
TaskManagerApp/
│
├── Models/
├── Views/
├── ViewModels/
├── Services/
├── Commands/
├── App.xaml / App.xaml.cs
└── MainWindow.xaml
From App.xaml.cs:
services.AddSingleton<ITaskService, TaskService>();
services.AddSingleton<INavigationService, NavigationService>();
services.AddTransient<TaskListViewModel>();
services.AddTransient<AddTaskViewModel>();
services.AddSingleton<MainViewModel>();
services.AddSingleton<MainWindow>();- Singleton – shared for entire app
- Transient – new instance each time
- Scoped – not used (more relevant for web applications)
public class TaskItem
{
public int Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public bool IsCompleted { get; set; }
public TaskPriority Priority { get; set; }
}public class TaskListViewModel : BaseViewModel
{
private readonly ITaskService _taskService;
public TaskListViewModel(ITaskService taskService)
{
_taskService = taskService;
}
public ObservableCollection<TaskViewModel> Tasks { get; }
public ICommand AddTaskCommand { get; }
public ICommand DeleteTaskCommand { get; }
}<ItemsControl ItemsSource="{Binding Tasks}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Title}" />
<Button Command="{Binding DataContext.DeleteTaskCommand,
RelativeSource={RelativeSource AncestorType=ItemsControl}}"
CommandParameter="{Binding}" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>cd TaskManagerApp
dotnet restore
dotnet build
dotnet runOpen the project and press F5.
- MVVM keeps UI logic clean and separated
- DI improves code organization and testability
- Commands keep UI interactions out of the code-behind
- Observable collections and property notifications drive UI updates
- Add validation (
INotifyDataErrorInfo) - Async commands
- Local persistence using EF Core + SQLite
- ViewModel unit tests
- More advanced DI patterns (factories, decorators, etc.)
- Binding errors → check Output window
- Unresolved services → verify registration in
App.xaml.cs - Commands not executing → ensure
CanExecutereturns true and binding paths are correct
- MVVM (Microsoft Docs)
- WPF Data Binding
- .NET Dependency Injection
- CommunityToolkit.MVVM
