View ↔ ViewModel mapping infrastructure for the Dreamine MVVM framework.
This library provides a lightweight ViewModel locator that supports convention-based resolution, manual registration, reverse view resolution, and Dependency Injection integration.
It is designed as a platform-agnostic mapping engine. It focuses on finding the correct ViewModel type from a View type, or the correct View type from a ViewModel type, using naming and namespace conventions.
WPF-specific concerns such as DataContext, FrameworkElement, and Loaded event wiring should be handled outside this library.
- Convention-based View ↔ ViewModel mapping
- Manual ViewModel registration
- Optional DI resolver integration
- Automatic assembly scanning
- Reverse View resolution from ViewModel
- Reset and cache clearing APIs for tests and application reconfiguration
- Root namespace lookup support
- Nested namespace and subfolder lookup support
- Flexible namespace candidate expansion for structures such as:
ViewsViewPagesWindowsDialogsGUIGUIsScreensControls
Dreamine.MVVM.Locators is not intended to be tied directly to WPF-only types.
Its responsibility is:
- resolve ViewModel types from View types
- resolve View types from ViewModel types
- provide a consistent convention engine
- support manual overrides and DI-based creation
Its responsibility is not:
- setting
DataContext - subscribing to
Loadedevents - checking
Window,Page, orUserControlinheritance
Those platform-specific behaviors should be implemented in a separate WPF-focused layer.
The locator resolves types in the following order.
- Manual registration map
- Convention-based namespace candidates
- Parent namespace expansion
- Root namespace lookup
- Assembly-wide fallback by type name
Example candidates for a View named MainWindow:
MyApp.ViewModels.MainWindowViewModelMyApp.Views.Admin.MainWindow→MyApp.ViewModels.Admin.MainWindowViewModelMyApp.GUI.Login.MainWindow→MyApp.ViewModels.Login.MainWindowViewModelMyApp.MainWindowViewModel
- Convention-based namespace candidates
- Parent namespace expansion
- Root namespace lookup
- Assembly-wide fallback by type name
namespace MyApp;
public partial class MainWindow
{
}
public sealed class MainWindowViewModel
{
}namespace MyApp.Views;
public partial class MainWindow
{
}
namespace MyApp.ViewModels;
public sealed class MainWindowViewModel
{
}namespace MyApp.Views.Admin;
public partial class MainWindow
{
}
namespace MyApp.ViewModels.Admin;
public sealed class MainWindowViewModel
{
}namespace MyApp.GUI.Account;
public partial class LoginDialog
{
}
namespace MyApp.ViewModels.Account;
public sealed class LoginDialogViewModel
{
}ViewModel instances are created through a registered resolver.
resolver.Resolve(vmType)There is no Activator.CreateInstance fallback for ViewModel creation. If no resolver is registered, or if the resolver returns null, Resolve(...) throws an InvalidOperationException with a message that distinguishes those two cases.
ViewModelLocator.RegisterResolver(new MyResolver());ViewModelLocator.Clear(); // clears mappings and lookup caches, keeps resolver
ViewModelLocator.ClearResolver(); // removes the resolver only
ViewModelLocator.Reset(); // clears mappings, lookup caches, and resolverReset() is useful for unit-test isolation. Clear() is useful when mappings should be rebuilt while keeping the same DI strategy.
ViewModelLocator.Register(typeof(MainWindow), typeof(MainWindowViewModel));var vm = ViewModelLocator.Resolve(typeof(MainWindow));var view = ViewModelLocator.ResolveView(typeof(MainWindowViewModel));ViewModelLocator.RegisterAll(Assembly.GetExecutingAssembly());The locator supports broad matching, but the recommended structure is still:
ViewsViewModels
This keeps projects predictable and reduces ambiguity when multiple candidates share the same type name.
- Broad matching improves flexibility, but duplicate type names can cause ambiguous fallback resolution.
- When multiple candidates may exist, prefer manual registration.
- Use this library for mapping and creation, not for platform event wiring.
- AppDomain type scans are cached and invalidated when a new assembly is loaded or when
Clear()/Reset()is called.
MIT License