Méthode directe dans le ViewModel
Une approche rapide consiste à intégrer l'appel à MessageBox dans le ViewModel, mais cela compromet la testabilité et la séparation des préoccupations.
private NetworkAdapterDto? _chosenAdapter;
[RelayCommand]
private void ExecuteAdapterSelection()
{
if (_chosenAdapter == null)
{
MessageBox.Show("Veuillez sélectionner un adaptateur réseau !", "Attention", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
MessageBox.Show($"Adaptateur sélectionné : {_chosenAdapter.Name}", "Succès");
}
public MainViewModel()
{
AvailableAdapters = new ObservableCollection<NetworkAdapterDto>
{
new NetworkAdapterDto { Name = "Ethernet", Address = IPAddress.Parse("192.168.1.10") },
new NetworkAdapterDto { Name = "Wi-Fi", Address = IPAddress.Parse("192.168.1.20") }
};
}
Implémentation avec injection de dépendances
En utilisant une intefrace pour les services de dialogue, on découple l'interaction UI. Le ViewModel communique via une abstraction, permettant une meilleure maintenabilité et testabilité.
public interface IDialogService
{
void DisplayWarning(string content);
}
public class DialogBoxService : IDialogService
{
public void DisplayWarning(string content)
{
MessageBox.Show(content, "Information", MessageBoxButton.OK, MessageBoxImage.Warning);
}
}
private readonly IDialogService _dialogHandler;
public MainViewModel(IDialogService dialogService)
{
_dialogHandler = dialogService;
LoadAdapters();
}
[RelayCommand]
private void HandleSelection()
{
if (_chosenAdapter == null)
{
_dialogHandler.DisplayWarning("Aucun adaptateur sélectionné !");
return;
}
_dialogHandler.DisplayWarning($"Adaptateur choisi : {_chosenAdapter.Name}");
}
Fonctionnalité étendue : désactivation automatique du bouton
Pour améliorer l'expérience utilisateur, le bouton peut être désactivé si aucun adaptateur n'est sélectionné. Utilisez la propriété CanExecute dans CommunityToolkit.Mvvm.
[RelayCommand(CanExecute = nameof(IsSelectionValid))]
private void HandleSelection()
{
// Logique existante...
}
private bool IsSelectionValid() => _chosenAdapter != null;
Configuration du conteneur IoC
Pour gérer les dépendances, configurez un conteneur d'injection de contrôles dans le point d'entrée de l'application.
// Dans App.xaml.cs
public partial class App : Application
{
public App()
{
Ioc.Default.ConfigureServices(
new ServiceCollection()
.AddSingleton<IDialogService, DialogBoxService>()
.AddTransient<MainViewModel>()
.BuildServiceProvider()
);
}
protected override void OnStartup(StartupEventArgs e)
{
var mainWindow = new MainWindow();
mainWindow.Show();
base.OnStartup(e);
}
}
Résolution des dépendances dans la vue
Dans le fichier code-behind de la fenêtre, récupérez le ViewModel via le conteneur.
// Dans MainWindow.xaml.cs
public MainWindow()
{
InitializeComponent();
DataContext = Ioc.Default.GetService<MainViewModel>();
}
Points clés et considérations
Le conteneur IoC résout automatiquemant les dépendances du constructeur du ViewModel, éliminant le besoin de paramètres manuels. La durée de vie des services est configurable : singleton pour les partages globaux, transient pour les instances uniques. Configurer l'IoC dans App.xaml.cs garantit l'initialisation avant la création des fenêtres. Pour les projets complexes, des conteneurs plus avancés comme Microsoft.Extensions.DependencyInjection peuvent être intégrés, mais l'implémentation native de CommunityToolkit.Mvvm suffit souvent.
En cas d'absence du constructeur App() dans App.xaml.cs, il peut être ajouté manuellement. Assurez-vous de supprimer toute propriété StartupUri dans App.xaml et de créer la fenêtre principale dans OnStartup si nécessaire. Lorsque plusieurs ViewModels nécessitent le service de dialogue, enregistrez-les tous dans le conteneur pour une gestion centralisée.