Bonjour,
Je débute avec MVVM et l'excellent MVVM Light de Laurent Bugnion. Je créé une appli avec une vue maître et une vue détail, et dans ma vue maître j'ai une TextBox qui permet à l'utilisateur de rechercher un texte et une listBox qui met en jour en temps réel son contenu en fonction de la frappe utilisateur. Ensuite, en sélectionnant un des items de la listBox présenté lorsque la recherche est terminée, la vue détail sera peuplée.
Pour le moment, j'ai créé mes entités avec Entity Framework. J'arrive à lancer ma recherche lorsque le contenu de ma TextBox est modifié avec un EventToCommand :
XAML :
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
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 <UserControl x:Class="TrackTime.Views.MasterViewUserControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras" mc:Ignorable="d" d:DesignHeight="600" d:DesignWidth="400" Background="#FFCE2D2D" DataContext="{Binding Master, Source={StaticResource Locator}}"> <Grid Background="#FF6C5656"> <Grid.RowDefinitions> <RowDefinition Height="200" /> <RowDefinition Height="Auto" /> <RowDefinition Height="400*" /> </Grid.RowDefinitions> <DockPanel Height="70" DockPanel.Dock="Top" Margin="0,0,0,130"> <TextBox Style="{DynamicResource WaterMarkTextBoxStyle}" Name="TextBoxSortProjects" Height="50" Margin="10" FontFamily="Myriad Pro" FontSize="32" VerticalContentAlignment="Center" Text="{Binding SearchedText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"> <i:Interaction.Triggers> <i:EventTrigger EventName="TextChanged"> <cmd:EventToCommand Command="{Binding SortTextChanged}"/> </i:EventTrigger> </i:Interaction.Triggers> </TextBox> </DockPanel> <DockPanel Grid.Row="2" Name="dockPanel1" DockPanel.Dock="Top" > <ListBox Name="listBoxProjects" Margin="10"> </ListBox> </DockPanel> </Grid> </UserControl>
VM :
Code c# : 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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106 public class MasterProjectsViewModel : ViewModelBase { #region Variables DataBaseModel_Container _context = new DataBaseModel_Container(); #endregion /// <summary> /// Initializes a new instance of the MasterProjectsViewModel class. /// </summary> public MasterProjectsViewModel() { SortTextChanged = new RelayCommand(TextChangedCommand, TextChangedCommandCanExecute); GetProjects = new RelayCommand(getProjects); getAllProjects(); } #region Properties #region SearchedText property /// <summary> /// The <see cref="SearchedText" /> property's name. /// </summary> public const string SearchedTextPropertyName = "SearchedText"; private string _searchedText = String.Empty; /// <summary> /// Sets and gets the SearchedText property. /// Changes to that property's value raise the PropertyChanged event. /// </summary> public string SearchedText { get { return _searchedText; } set { if (_searchedText == value) { return; } _searchedText = value; RaisePropertyChanged(SearchedTextPropertyName); } } #endregion #endregion #region Commands #region SearchEntry Command public RelayCommand SortTextChanged { get; private set; } private void TextChangedCommand() { getProjects(); } private bool TextChangedCommandCanExecute() { bool isExecutable = (_searchedText.Length > 3) ? true : false; return isExecutable; } #endregion #region GetProjects Command public RelayCommand GetProjects { get; private set; } private void getProjects() { var matchingProjectsRequest = from projects in _context.ProjectJeu where (projects.Name.Contains(_searchedText) || (projects.Description.Contains(_searchedText))) select projects; //Comment faire un binding propre? } private void getAllProjects() { var allProjectsRequest = from projects in _context.ProjectJeu select projects; //if (e != null) } #endregion #endregion }
Je suis absolument fan du découplage complet entre l'Ui et la VM que MVVM offre. Sauf que là, je ne vois pas comment bien binder mon résultat de requête LINQ to Entity qui est déclenché lorsqu'on tape dans la TextBox... Tous les exemples que j'ai vu le font en code-behind sur la vue, en liant fortement la listbox à la logique métier.
Quelles sont les bonnes pratiques pour que mon binding se fasse entre le résultat de ma requête LINQ to Entities et ma listBox sans qu'à aucun moment la VM n'aie à savoir que c'est une listBox qui affiche dans la vue?
Quelles sont les bonnes pratiques là-dessus? J'avais commencé à faire une commande toute simple que je bindais sur ma ListBox, mais une fois dans la VM je ne voyais pas comment faire... Avec une propriété qui expose ma ListBox? Mais ça voudrait dire que c'est fortement lié entre la VM et l'UI...
Bref, je nage ! J'espère avoir été clair, merci d'avance pour vos lumières !
N'hésitez pas à me demander plus d'informations.
Nicolas
Partager