Architecture logicielle et UML
La boîte de dialogue fonctionne – pour l'instant. Le code-behind compte deux mille lignes : des gestionnaires de clics lisent des champs de texte, calculent, écrivent dans le dessin et activent ou désactivent des boutons. Chaque nouvelle exigence la rend plus fragile, et on ne peut la tester qu'en cliquant. MVVM remet de l'ordre.
Trois rôles
- View : l'interface en XAML. Elle affiche et reçoit les saisies. Elle ne connaît le ViewModel qu'à travers les liaisons.
- ViewModel : l'état et les commandes de l'interface sous forme de classe C# ordinaire – sans lien avec les fenêtres, les champs de texte ou les couleurs.
- Model : la logique métier et les données, y compris, derrière des interfaces, l'accès à la base de données, aux appareils ou à la CAO.
La connexion est assurée par la liaison de données de WPF. Lorsqu'une propriété change dans le ViewModel, celui-ci le signale via INotifyPropertyChanged, et l'interface suit. Un bouton ne déclenche plus d'événement Click, mais une commande, un ICommand. Le gain : le ViewModel peut être testé sans interface, et l'interface peut être remaniée sans toucher à la logique.
Le ViewModel
Un petit exemple : l'utilisateur saisit une largeur, et le bouton « Zeichnen » (Dessiner) n'est actif que si la saisie est valide.
public class ParameterViewModel : INotifyPropertyChanged
{
private readonly IZeichnungsDienst _zeichnung;
private string _breite = "100";
public ParameterViewModel(IZeichnungsDienst zeichnung)
{
_zeichnung = zeichnung;
ZeichnenBefehl = new RelayCommand(Zeichne, () => IstGültig);
}
public event PropertyChangedEventHandler PropertyChanged;
public string Breite
{
get => _breite;
set
{
if (_breite != value)
{
_breite = value;
Melde(nameof(Breite));
ZeichnenBefehl.MeldeÄnderung(); // réévaluer le bouton
}
}
}
public bool IstGültig => double.TryParse(Breite, out var wert) && wert > 0;
public RelayCommand ZeichnenBefehl { get; }
private void Zeichne() => _zeichnung.ZeichneRechteck(double.Parse(Breite));
private void Melde(string name) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
public class RelayCommand : ICommand
{
private readonly Action _ausführen;
private readonly Func<bool> _darfAusführen;
public RelayCommand(Action ausführen, Func<bool> darfAusführen = null)
{
_ausführen = ausführen;
_darfAusführen = darfAusführen;
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter) => _darfAusführen?.Invoke() ?? true;
public void Execute(object parameter) => _ausführen();
public void MeldeÄnderung() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
On écrit le RelayCommand une fois et on l'utilise partout. Qui veut s'épargner cette répétition prend le paquet CommunityToolkit.Mvvm : avec les attributs [ObservableProperty] et [RelayCommand], un générateur de source produit ce code à la compilation. Le paquet fonctionne aussi sous .NET Framework 4.8 et donc dans les add-ins pour d'anciennes versions d'AutoCAD.
La View ne fait que lier
<StackPanel Margin="12">
<Label Content="Breite (mm)" Target="{Binding ElementName=BreiteFeld}" />
<TextBox x:Name="BreiteFeld"
Text="{Binding Breite, UpdateSourceTrigger=PropertyChanged}" />
<Button Content="Zeichnen" Command="{Binding ZeichnenBefehl}" Margin="0,8,0,0" />
</StackPanel>
Dans le code-behind, il reste une ligne : DataContext = new ParameterViewModel(dienst);. UpdateSourceTrigger=PropertyChanged fait en sorte que le bouton réagisse dès la frappe et pas seulement lorsque l'utilisateur quitte le champ.
MVVM dans l'add-in de CAO
MVVM est particulièrement rentable dans les palettes et boîtes de dialogue des add-ins de CAO. Le ViewModel n'y appelle pas l'API AutoCAD, mais une interface comme IZeichnungsDienst. Seule son implémentation travaille avec AutoCAD et prend en charge ce qui s'y applique :
- Une palette vit plus longtemps que n'importe quel dessin. L'implémentation récupère donc le document actif à chaque appel via
MdiActiveDocumentet vérifie qu'il n'est pasnull. - Les clics s'exécutent en dehors de toute commande, dans le contexte de l'application. Qui modifie directement le dessin le verrouille avec
LockDocument, sinon on obtientErrorStatus.LockViolation. Il est souvent préférable de lancer une commande avecSendStringToExecute. Elle apparaît dans la ligne de commande, possède sa propre étape d'annulation et peut être répétée.
Dans le test unitaire, le ViewModel reçoit une simulation de l'interface. Vous vérifiez ainsi les saisies, les commandes et les états en quelques millisecondes, sans qu'AutoCAD tourne. La séparation aide aussi lors d'un changement de plateforme : avec une autre implémentation du service, le même ViewModel peut être réutilisé dans BricsCAD ou Revit.
Jusqu'où aller
MVVM est un outil, pas un dogme. Le code qui ne concerne que l'affichage – placer le focus, lancer une animation – peut rester dans le code-behind. Le ViewModel appelle les boîtes de message et les boîtes de dialogue de fichiers via un service dédié, afin que les tests ne restent pas bloqués sur une fenêtre. Et pour les validations de saisie qui doivent apparaître directement au niveau du champ, il existe INotifyDataErrorInfo.
Erreurs typiques
- Le ViewModel connaît des contrôles, des couleurs ou
MessageBox. Il n'est alors plus testable sans interface. - Oublier
PropertyChangedou le déclencher avec un nom mal orthographié.nameofaide. - Ne jamais déclencher
CanExecuteChanged. Le bouton reste grisé alors que la saisie est correcte. - Lier des listes sous forme de
List<T>au lieu d'ObservableCollection<T>– les nouvelles entrées n'apparaissent pas. - Dans l'add-in de CAO, conserver dans le ViewModel un dessin qui est fermé depuis longtemps.
- Ne pas voir les erreurs de liaison. Elles n'apparaissent que dans la fenêtre Sortie de Visual Studio, pas sous forme d'exception.
Comment nous vous aidons
- Formation : la formation WPF mène du XAML à MVVM en passant par la liaison de données. La formation « C# & .NET (avancés) » approfondit les patrons de conception et l'architecture.
- Modernisation : nous faisons évoluer progressivement vers MVVM des interfaces WinForms ou WPF qui ont grandi au fil du temps, y compris dans les add-ins de CAO : les interfaces utilisateur chez Cadida.
- Votre projet : Convenez d'un premier entretien.
Sources : Ebi F. Eilber, AutoCAD .NET API (ouvrage spécialisé, parution prévue en 2027), chapitre « Programmation d'interfaces graphiques » ; Microsoft Learn : liaison de données dans WPF ; Microsoft Learn : MVVM Toolkit.
