Bonjour,
Je suis débutant en WPF avec le Design Pattern MVVM et je souhaite respecter au maximum celui-ci.
J'ai commencé pour mon application, à créer un petit UserControl qui va gère les action Agrandir/Réduire/fermer des fenêtres (afin de personnaliser leur design)
Mon UserControl a des DependencyProperty permettant d'afficher ou non chaque bouton.
View.MyUserControl.WinControls
Code XAML : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 <StackPanel Orientation="Horizontal"> <Button x:Name="MinBoxUI" Command="{Binding MinimizeWindowCommand}" Style="{StaticResource WinControlStyle}" Content="{DynamicResource window-minimize}" Visibility="{Binding Path=MinimizeBox}"/> <Button x:Name="MaxBoxUI" Command="{Binding MaximizeWindowCommand}" Visibility="{Binding Path=MaximizeBox}"> <Button.Style> <!-- On surcharge le style WinControlStyle (Héritage BasedOn)--> <Style TargetType="{x:Type Button}" BasedOn="{StaticResource WinControlStyle}"> <Setter Property="Content" Value="{DynamicResource window-maximize}"></Setter> <Style.Triggers> <!-- Changement du glyph du bouton en fonction de l'état actuel de la fenêtre--> <DataTrigger Binding="{Binding WindowState, RelativeSource={RelativeSource AncestorType=Window}}" Value="Maximized"> <Setter Property="Content" Value="{DynamicResource window-restaure}"/> </DataTrigger> </Style.Triggers> </Style> </Button.Style> </Button> <Button x:Name="CloseBoxUI" Command="{Binding CloseWindowCommand}" Style="{StaticResource WinControlStyle}" Content="{DynamicResource window-close}" Visibility="{Binding Path=CloseBox}"/> </StackPanel>
Le code Behind de la View sert uniquement à créer les DependancyProperties de mon UserControl.
View.MyUserControl
Code VB : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 Imports System.ComponentModel Namespace View.MyUserControl Partial Public Class WinControls Inherits Controls.UserControl Public Shared ReadOnly MaximizeBoxProperty As DependencyProperty = DependencyProperty.Register("MaximizeBox", GetType(Windows.Visibility), GetType(WinControls), Nothing) Public Shared ReadOnly MinimizeBoxProperty As DependencyProperty = DependencyProperty.Register("MinimizeBox", GetType(Windows.Visibility), GetType(WinControls), Nothing) Public Shared ReadOnly CloseBoxProperty As DependencyProperty = DependencyProperty.Register("CloseBox", GetType(Windows.Visibility), GetType(WinControls), Nothing) <Description("Vibilité du bouton réduire"), Category("Visibility")> Public Property MaximizeBox As Windows.Visibility Get Return CType(GetValue(MaximizeBoxProperty), Windows.Visibility) End Get Set(value As Windows.Visibility) SetValue(MaximizeBoxProperty, value) End Set End Property <Description("Vibilité du bouton agrandir"), Category("Visibility")> Public Property MinimizeBox As Windows.Visibility Get Return CType(GetValue(MinimizeBoxProperty), Windows.Visibility) End Get Set(value As Windows.Visibility) SetValue(MinimizeBoxProperty, value) End Set End Property <Description("Visibilité du bouton fermer"), Category("Visibility")> Public Property CloseBox As Windows.Visibility Get Return CType(GetValue(CloseBoxProperty), Windows.Visibility) End Get Set(value As Windows.Visibility) SetValue(CloseBoxProperty, value) End Set End Property Sub New() ' Cet appel est requis par le concepteur. InitializeComponent() ' Ajoutez une initialisation quelconque après l'appel InitializeComponent(). Me.DataContext = Me End Sub End Class End Namespace
De cette manière ci, les propriétés de mon UserControl (CloseBox, MaximizeBox, MiniMizeBox) sont bien répercutés quand j'utilise mon UserControl. Cependant mes Commandes qui sont dans un fichier ViewModel ne fontionne pas, ce qui est normal car le contexte défini par mon contrôle est "lui-même".
Du coup si je change le DataContext pour mon ViewModel, les commandes fonctionnent mais pas les propriétés de dépendances.
ViewModel.WinControlViewModel
Code VB : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 Imports System.ComponentModel Imports System.Runtime.CompilerServices Namespace ViewModel Public Class WinControlsViewModel #Region "####### GESTIONNAIRE DE COMMANDES ###################" Private _CloseWindowCommand As Commands.RelayCommand(Of Application) = New Commands.RelayCommand(Of Application)(AddressOf Me.CloseWindow) Private _MinimizeWindowCommand As Commands.RelayCommand(Of Window) = New Commands.RelayCommand(Of Window)(AddressOf Me.MinimizeWindow) Private _MaximizeWindowCommand As Commands.RelayCommand(Of Window) = New Commands.RelayCommand(Of Window)(AddressOf Me.MaximizeWindow) Public ReadOnly Property CloseWindowCommand As Commands.RelayCommand(Of Application) Get Return _CloseWindowCommand End Get End Property Public ReadOnly Property MinimizeWindowCommand As Commands.RelayCommand(Of Window) Get Return _MinimizeWindowCommand End Get End Property Public ReadOnly Property MaximizeWindowCommand As Commands.RelayCommand(Of Window) Get Return _MaximizeWindowCommand End Get End Property Private Sub CloseWindow(ByVal App As Application) Application.Current.Shutdown() End Sub Private Sub MinimizeWindow() Application.Current.MainWindow.WindowState = WindowState.Minimized End Sub Private Sub MaximizeWindow() Select Case Application.Current.MainWindow.WindowState Case WindowState.Normal Application.Current.MainWindow.WindowState = WindowState.Maximized Case WindowState.Maximized Application.Current.MainWindow.WindowState = WindowState.Normal End Select End Sub #End Region End Class End Namespace
Dans le code Behind de la vue, j'ai tenté de mettre une Public Property référençant mon ViewModel de cette manière :
View.MyUserControl
Code VB : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 Private _VMDataContext As ViewModel.WinControlsViewModel Public ReadOnly Property VMDataContext As ViewModel.WinControlsViewModel Get Return _VMDataContext End Get End Property Sub New() ' Cet appel est requis par le concepteur. InitializeComponent() _VMDataContext = New ViewModel.WinControlsViewModel ' Ajoutez une initialisation quelconque après l'appel InitializeComponent(). Me.DataContext = Me End Sub
et du coup je Bind mes commandes comme ceci :
Code XAML : Sélectionner tout - Visualiser dans une fenêtre à part
1
2<Button x:Name="CloseBoxUI" Command="{Binding VMDataContext.CloseWindowCommand}" Style="{StaticResource WinControlStyle}" Content="{DynamicResource window-close}" Visibility="{Binding Path=CloseBox}"/>
Du coup tout fonctionne mais ma grande question est: Est ce que c'est la meilleur méthode ?
J'ai cru comprendre qu'il fallait garder la création des DependencyProperty dans le Code-Behind de la View mais que les différents traitements devaient être réalisés dans le ViewModel.
Du coup comment garder l'esprit MVVM en gérant le Contexte de la vue pour les DependencyProperty et les traitements de du ViewModel ?
Je n'arrive pas à trouver de réponse concrète sur ces interactions.
Merci d'avance si vous avez de quoi m'aiguiller
Bonne journée à vous !
Partager