Je cherche à découvrir les structures (ou les architectures) des applications WPF, j'ai découvert plusieurs Templates d'applications WPF avec des Galeries de Composants Graphiques Utilisateurs et je vois beaucoup de code derrière alors à quoi sert-il, pourquoi tout ce code ?
Je zoom sur Wpf.UI du projet :
GitHub WPF-UI Lepo.co
WPF-UI se trouve en package nuget téléchargeable indépendamment :
NuGet Gallery | WPF-UI 2.0.3
Pour la Librairie WPF-UI utilisée en référence dans le projet :
\Lepoco-WpfUI\src\Wpf.Ui.Gallery\Wpf.Ui.Gallery.csproj
On trouve la structure suivante :
|
Lepo Wpf.UI - Structure |
La seule dépendance de Wpf.Ui en dehors du framework c'est : System.Drawing.Common
Microsoft Learn - System.Drawing.Common .NET
En essayant de comparer la structure de cette application WPF avec le projet :
GitHub-Kinnara - ModernWpf
Qui lui ne fait aucune référence à System.Drawing.Common...
Je vais utiliser un troisième modèle de comparaison car Kinnara me semble ne pas utiliser les structures nécessaires pour utiliser le modèle MvvM qui est acquis maintenant.
Et la base de tous certainement :
GitHub - MahApps
On ne conçoit pas de développer une application conséquente sans structuration par MvvM, injection des dépendances, ... aussi je me lance dans un premier template :
GitHub-mabyre/WpfAppRibbonTemplateStudio
A partir de TemplateStudio le modèle Ribbon - Prism
Il me semble qu'en démarrant directement un projet à l'aide de TemplateStudio, je passe à côté de nombreuses problématiques, du coup je vais décrire les Samples des projets que j'ai déjà récoltés. Afin d'en découvrir la structure.
A force de me promener dans ces différents projets, je trouve un truc que je crois être cool, pour traiter les icônes dans :
\\Visual Studio 2022\Samples\Kinnara-ModernWPF\ModernWPF Net6-7\ModernWPF\ModernWpf\IconElement\Symbol.cs
Mais cela va me mener encore plus bas dans l'OS MS... dans le traitement des icônes.
Les projets de Modern UI pour WPF ont tous une grosse librairie associée dont voici une description succincte des dépendances afin de mieux saisir comment elles sont imbriqués dans l'OS MS ou framework :
Fluent.Ribbon
System.Windows.Documents.Adorner
System.Windows.FrameworkElementSystem.Windows.DependencyObject
System.Windows.DependencyProperty
System.ComponentModel.INotifyPropertyChanged
System.Windows.Automation.Peers.FrameworkElementAutomationPeer
System.Collections.ObjectModel.ObservableCollection
System.Windows.Controls.ItemsControl
System.Windows.RoutedEventArgs : EventArgs
System.Windows.Data.IValueConverter
System.Windows.Data.IMultiValueConverter
MahApps.Metro
System.Windows.FrameworkElement
Microsoft.Xaml.Behaviors.TriggerAction<T>
Microsoft.Xaml.Behaviors.Behavior<T>
ControlzEx.Behaviors.WindowChromeBehavior
System.Windows.DependencyObject
System.Window.VisualStateManager : DependencyObject System.Windows.DependencyProperty
System.Windows.Automation.Peers.FrameworkElementAutomationPeer
System.Windows.Point
System.Windows.Controls.Primitives
System.Windows.FreezableCollection<T>
System.Windows.Controls.Control : FrameworkElement
System.IEquatable<T>
System.Windows.Controls.ContentControl
System.Windows.Controls.HeaderedContentControl : ContentControl
System.Windows.RoutedEventArgs : EventArgs
System.Resources.ResourceManager
System.Windows.Data.IValueConverter
System.Windows.Markup.MarkupExtension
Wpf.Ui Lepo
System.Windows.Input.ICommand
System.Action<T?>
System.PlatformIDSystem.Windows.Controls.ContentControl
System.Windows.Clipboard
System.Windows.RoutedEventHandler
System.Windows.RoutedEvent
System.Windows.DependencyProperty
System.Drawing.ToolboxBitmap
System.Windows.Window
System.Windows.Interop.WindowInteropHelper
System.Windows.Data.IValueConverter
System.Windows.Data.IMultiValueConverter
System.Windows.SystemParameters
System.Windows.Point
System.Windows.Media.RenderCapability
System.Runtime.InteropServices
System.Windows.Interop
La partie de la Lib Wpf.Ui concernant l'Interop (interopérabilité) est instructive je vous la conseil
System.Windows.ResourceDictionary
System.ComponentModel
System.Windows.Markup
System.Windows.DynamicResourceExtension
ModernWPF by Kinnara
Cette Librairie modern WPF semble prendre ses racines encore plus loin dans l'OS MS. Voici donc quelques références loin loin dans le framework MS.
Je note ici les dépendances qui ne sont pas dans les autres projets (ou que je n'ai pas trouvé).
System.WeakReference<T> : ISerializable where T : class (allow object to control its own serial/deserial)
System.Resources.ResourceManager gestion de la localization
TypedEventHandler<TSender, TResult>(TSender sender, TResult args)
System.Windows.Freezable : DependencyObject
System.Windows.Media.Geometry
System.Windows.Controls.ContentPresenter : FrameworkElement
System.Windows.CornerRadius : IEquatable<CornerRadius>
...
Dépendances des Librairies Modern UI
C'est un travail fastidieux mais il permet de rendre compte de l'imbrication de ces librairies avec le framework (ou les frameworks .NET Framework 4.6.2 - 4.7 .NET Core 3.1).
Des trois librairies Wpf.Ui est un peu différentes car elle ne s’appuie que sur le framework .NET 6.0. mais Wpf.Ui descend très profondément dans la tripaille de Windows, avec des objets comme Interop et InterropServices qui sont bas dans l'OS et en redéfinissant par exemple le "Point".
Fluent.Ribbon est la plus simple des trois librairies c'est certainement lié au fait qu'elle ne se préoccupe que de l'objet Ribbon.
On peut constater que les ModernWpfUI ont encore besoin de beaucoup de code pour fonctionner.
WPF Modern Application - Structure
A ce stade, il est important de faire la liste des sujets que l'on va aborder Ici. Car petit à petit en progressant, je me rends compte qu'ils sont nombreux. Les différentes documentation sont pléthoriques.
Donc quels sont les grands sujets concernant l'architecture des applications WPF ?
Microsoft Learn - Vue d’ensemble des bibliothèques runtime
Cette page nous propose les sujets de structuration de votre application WPF suivants :
Voilà déjà une liste des sujets proposés par Microsoft Learn.
Démarrage
Navigation
MVVM
WPF Modern Application - Démarrage & Navigation
Le démarrage d'une application WPF dépend des choix concernant la Navigation entre les Page, Windows ou UserControl.
La Navigation est le premier Sujet d'une application WPF.
Stack Overflow -Window vs Page vs UserControl for WPF navigation ?
Les trois objets de la Navigation sont :
- Window quand vous souhaitez faire apparaître une nouvelle fenêtre
- Page qui est à l'intérieur d'une fenêtre plutôt utilisée dans les systèmes à base de Web comme XBAP
- UserControl qui contient des contrôles créés dynamiquement comme lorsque l'on utilise le pattern MVVM
Avec Prism les ViewModel dérivent de BindableBase
avec Community.Mvvm ils dérivent de ObservableObject.
Les deux Modèles Prism et Community.Mvvm sont assez différents, il y a bon nombre de lignes de code qui diffèrent.
Fluent.Ribbon - Showcase
App.xaml : StartupUri="TestWindow.xaml"
App.xaml.cs : Gestion des Theme par ControlzEx
Button Click="OpenRibbonWindowColorized_OnClick"
private void OpenRibbonWindowColorized_OnClick(object sender, RoutedEventArgs e)
{
new RibbonWindowColorized().Show();
}
MahApps.Metro - Demo
App.xaml : StartupUri="MainWindow.xaml"
MainWindow.xaml.cs :
public partial class MainWindow : MetroWindow : Window PART_Icon, PART_TitleBar
{
public MainWindow()
{
_viewModel = new MainWindowViewModel(DialogCoordinator.Instance);
DataContext = _viewModel;
public class MainWindowViewModel : ViewModelBase, IDataErrorInfo, IDisposable
{
this.Title = "Flyout Binding Test";
this._dialogCoordinator = dialogCoordinator;
SampleData.Seed();
Focus sur le bouton du menu : "Show InputDialog"
MahApps.Metro.Samples\MahApps.Metro.Demo\MainWindow.xaml
<MenuItem Click="ShowInputDialog" Header="Show InputDialog" />
\MahApps.Metro.Samples\MahApps.Metro.Demo\MainWindow.xaml.cs
private async void ShowInputDialog(object sender, RoutedEventArgs e)
{
var result = await this.ShowInputAsync("Hello!", "What is your name?");
if (result == null) //user pressed cancel
return;
await this.ShowMessageAsync("Hello", "Hello " + result + "!");
}
Vu comment cela est architecturé, on aurait du mal à passer le résultat de ces boites de dialogues dans le ViewModel de la fenêtre principale...
ModernWPF by Kinnara
Rien dans App.xaml.cs, App.xml fait un StartupUri="MainWindow.xaml" et pour la Navigation ils utilisent public partial class NavigationRootPage :
\ModernWpf.SampleApp\Navigation\NavigationRootPage.xaml.cs
public class partial NavigationRootPage
Wpf.Ui Lepo
Dans Wpf.Ui.Demo.Mvvm l'application démarre grâce à Microsoft.Extensions.Hosting :
\\Lepoco-WpfUI\src\Wpf.Ui.Gallery\App.xaml.cs
https://docs.microsoft.com/dotnet/core/extensions/generic-host
https://docs.microsoft.com/dotnet/core/extensions/dependency-injection
https://docs.microsoft.com/dotnet/core/extensions/configuration
https://docs.microsoft.com/dotnet/core/extensions/logging
Le parti pris de Lepo Wpf.UI est de ne pas utiliser Prism et cela va nous permettre de comparer les différentes architectures.
Là on est au cœur de la structuration ou architecture des applications Microsoft .NET.
Le début de la documentation concernant l'architecture des applications WPF :
Microsoft Learn - Vue d’ensemble des bibliothèques runtime
Avec Prism on a des UserControl avec CommunityToolkit.Mvvm Page
Prism UserControl vs CommunityToolkit.Mvvm Page
La Navigation est le premier sujet Wpf.Ui Lepo propose déjà trois Templates avec des modes de navigation, MS Store, Fluent et Compact...
Curieusement les trois Templates sont tout à fait équivalents aucun avec Prism.
TemplateStudio
La Navigation avec Prims semble plus simple, plus intégrée, le répertoire Services est moins rempli.
Configuration
Microsoft.Extensions.Hosting est remplacé par Prism.IoC.IContainerregistry.
To Be Continued...