J’essaie de configurer une application de style MVVM et je pense que je vais me perdre dans les interactions entre ces éléments, en espérant que quelqu’un pourra vous aider. Est-ce que je fais quelque chose de vraiment faux ici?
Je suppose que mes 2 questions principales sont
Mes cours (un peu simplifiés):
IFieldDescription
// Interface that is supposed to be the Model public interface IFieldDescription { Ssortingng Name { get; } bool Disabled { get; } }
NodeModel
// Class that is supposed to be the ViewModel public class NodeModel : NotifyPropertyChanged { internal NodeModel() { } public NodeModel(IFieldDescription fieldDescription) { this.FieldDescription = fieldDescription; } protected IFieldDescription FieldDescription { get { return this.fieldDescription; } set { this.fieldDescription = value; this.OnPropertyChanged("Name"); this.OnPropertyChanged("Disabled"); this.OnPropertyChanged("PrimaryKey"); } } private IFieldDescription fieldDescription; public Ssortingng Name { get { return this.FieldDescription.Name; } } public Boolean Disabled { get { return this.FieldDescription.Disabled; } } }
Code de nœud derrière
public Node(NodeModel model) { this.DataContext = model; this.InitializeComponent(); }
XAML
Fenêtre principale
<!---->
Le contexte de données pour la fenêtre principale est défini sur un nouveau RD () défini ci-dessous: RD
public class RD { private IEnumerable GetTestData() { yield return new FieldDescription("Ssortingng", true); yield return new FieldDescription("Integer", false); yield return new FieldDescription("Double", false); yield return new FieldDescription("Date", false); yield return new FieldDescription("Enum", false); } public virtual ObservableCollection FieldDescriptions { get { return new ObservableCollection(GetTestData()); } } }
Tout mon convertisseur est actuellement défini comme:
public class ModelToViewConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { if (value == null) return null; if (value is IFieldDescription) { NodeModel model = new NodeModel((IFieldDescription)value); return new Node(model); } return null; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } }
J’utilise généralement DataTemplates
pour lier une View
à un Model
ou à un Model
ViewModel
Le seul endroit où le code-behind de ma vue fait jamais référence à un modèle ou à un modèle de vue est au démarrage lorsqu’il définit ViewModel de démarrage en tant que DataContext de la vue de DataContext
. Tout le rest est DataTemplates
à DataTemplates
(ou DataTemplateSelectors
for Silverlight).
(En fait, pour être juste, je dois parfois faire quelque chose de spécial et je vais DataContext
le DataContext
un object en ViewModel ou en Modèle dans le code-behind, mais ces cas sont rares et je les considère comme des hacks)
Par exemple, en définissant le démarrage View / ViewModel:
public partial class App : Application { protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); var app = new ShellView(); var context = new ShellViewModel(); app.DataContext = context; app.Show(); } }
Voici un exemple de DataTemplates:
Et enfin, je vais utiliser ContentControls
dans mon XAML où je veux afficher mes vues
ou
Parfois, les ContentControls ne sont même pas nécessaires. Par exemple, si vous ListView
un ListView
à un ObservableCollection
, chaque élément du ListView
sera un object de type NodeModel
et WPF prendra automatiquement le DataTemplate pour cela.
L’idée derrière MVVM est que l’ensemble de votre application fonctionne dans vos ViewModels, et les vues sont simplement une jolie interface utilisateur qui s’ajoute aux ViewModels pour les rendre plus conviviales. Dans un monde parfait, la vue pourrait facilement être remplacée par une autre interface utilisateur.
Si vous êtes intéressé, j’ai un exemple simple MVVM sur mon blog qui contient quelques exemples d’utilisation du modèle de conception MVVM