WPF MVVM Patterns
Architecture
This project uses MVVM without a framework. Key base classes:
- •ViewModelBase (
ViewModels/ViewModelBase.cs):INotifyPropertyChangedwithSetProperty<T>helper - •RelayCommand (
ViewModels/RelayCommand.cs):ICommandimplementation withAction/Funcconstructors
Adding a New View + ViewModel
- •Create ViewModel in
ViewModels/:
csharp
namespace WinContextMenuEditor.ViewModels;
public class FooViewModel : ViewModelBase
{
private string _bar = string.Empty;
public string Bar
{
get => _bar;
set => SetProperty(ref _bar, value);
}
public ICommand DoSomethingCommand { get; }
public FooViewModel()
{
DoSomethingCommand = new RelayCommand(OnDoSomething);
}
private void OnDoSomething() { /* ... */ }
}
- •Create View XAML in
Views/:
xml
<UserControl x:Class="WinContextMenuEditor.Views.FooView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:WinContextMenuEditor.ViewModels">
<UserControl.DataContext>
<vm:FooViewModel/>
</UserControl.DataContext>
<!-- Use {Binding PropertyName} for data binding -->
</UserControl>
App-Level Resources
Registered in App.xaml:
- •
{StaticResource BoolToVis}-BoolToVisibilityConverter(supportsConverterParameter=Invert) - •
{StaticResource InvertBoolConverter}- inverts bool values - •Styles:
ActionButton,ToolbarButton,FormLabel,FormTextBox,SearchTextBox,CategoryListBox,StatusBar - •Strings:
{DynamicResource KeyName}for i18n (seeResources/Strings.*.xaml)
i18n
- •Add entries to both
Resources/Strings.en-US.xamlandResources/Strings.ja-JP.xaml - •Use
{DynamicResource StringKey}in XAML (not StaticResource - dynamic enables runtime switching)
Dialog Pattern
For modal dialogs (see AddEditDialog as example):
- •Create Window with
DataContextbound to dialog ViewModel - •Set
DialogResultin code-behind OK/Cancel click handlers - •Show with
dialog.ShowDialog() == true
Conventions
- •Properties: use
SetProperty(ref _field, value)for change notification - •Commands:
RelayCommandwithActionorAction<object?>+ optionalFunc<bool>canExecute - •Converters: register in
App.xamlResourceDictionary - •Keep code-behind minimal - logic in ViewModels, UI wiring only in code-behind