{"id":484,"date":"2013-06-23T20:08:46","date_gmt":"2013-06-23T18:08:46","guid":{"rendered":"http:\/\/dev.bratched.fr\/fr\/wpf-listview-dimages-mvvm-et-drag-and-drop-fin-3\/"},"modified":"2013-06-23T20:08:46","modified_gmt":"2013-06-23T18:08:46","slug":"wpf-listview-dimages-mvvm-et-drag-and-drop-fin","status":"publish","type":"post","link":"https:\/\/bratched.com\/fr\/2013\/06\/23\/wpf-listview-dimages-mvvm-et-drag-and-drop-fin\/","title":{"rendered":"WPF, ListView d\u2019images, MVVM et Drag and Drop\u2026 \u2013 Fin"},"content":{"rendered":"<h1 class=\"jfdefaulttext\">Introduction<\/h1>\n<p>Les projets pr\u00e9c\u00e9dents ont \u00e9t\u00e9 red\u00e9coup\u00e9s afin de fournir 2 assemblies directement utilisable.<\/p>\n<p>Pour ceux qui souhaitent ajouter rapidement un treeview d\u2019images avec une gestion de Drag&amp;Drop (Voir les 4 pr\u00e9c\u00e9dents chapitres ) voici les \u00e9tapes de r\u00e9alisation.<\/p>\n<p>L\u2019exemple suivant montre comment r\u00e9aliser une application respectant l\u2019architecture M-V-VM avec les briques Drag and Drop et Listview d\u2019images<\/p>\n<p><a href=\"http:\/\/www.bratched.com\/media\/C%C3%A9dric\/image11068185151.png\"><img decoding=\"async\" loading=\"lazy\" style=\"border-width: 0px\" title=\"Application M-V-VM exemple avec Liste en arbre de type TreeView\" src=\"http:\/\/dev.bratched.fr\/fr\/wp-content\/uploads\/sites\/2\/importedmedia\/blogmedia-image1-thumb816830504-png.png\" alt=\"Application M-V-VM exemple avec Liste en arbre de type TreeView\" width=\"529\" height=\"354\" border=\"0\" \/><\/a><\/p>\n<p>Il vous faudra :<\/p>\n<ol>\n<li>Ajouter les assemblies<\/li>\n<li>D\u00e9finir un objet poss\u00e9dant l\u2019Interface <strong>IImageFile<\/strong> (et <strong>IParentItem<\/strong> si vous souhaiter des structures hi\u00e9rarchiques)<\/li>\n<li>D\u00e9finir un objet ViewModel d\u00e9rivant de <strong>CustomImageFileViewModel<\/strong> si vous voulez g\u00e9rer le DragAndDrop provenant d\u2019applications externes<\/li>\n<li>Initialiser les images dans <strong>CollectionImageViewModel <\/strong><\/li>\n<\/ol>\n<h1>Impl\u00e9mentation<\/h1>\n<h2>Ajouts des assemblies<\/h2>\n<p>La premi\u00e8re \u00e9tape est de t\u00e9l\u00e9charger ou compiler les assemblies suivantes (\u00e0 la fin de l\u2019article) :<\/p>\n<ul>\n<li><strong>ImageFileListView<\/strong> : Contient la partie visuelle, le View Model et les interfaces du mod\u00e8le \u00e0 impl\u00e9menter<\/li>\n<li><strong>DragDropManager<\/strong> : Contient les m\u00e9canismes de Drag and Drop qui pourront \u00eatre appliqu\u00e9s sur la lise<\/li>\n<\/ul>\n<h2>Ajout de la liste dans la View<\/h2>\n<p>Pour ajouter la liste dans la View vous devez d\u00e9finir une r\u00e9f\u00e9rence dans le XAML \u00e0 l\u2019assemblie <strong>ImageFileListView<\/strong>.<\/p>\n<div id=\"scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:7082892f-8cd2-41a2-9066-c9a88b6778f7\" class=\"wlWriterEditableSmartContent\" style=\"margin: 0px;padding: 0px;float: none\">\n<pre>xmlns:m=\"clr-namespace:ImageFileListView.View;assembly=ImageFileListView\"<\/pre>\n<p><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http:\/\/dunnhq.com --><\/p>\n<\/div>\n<p><!--more--><\/p>\n<p>Dans le code XAML ajouter le composant de la fa\u00e7on suivante<\/p>\n<div id=\"scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:6a6e8259-be9b-48a7-80fd-d859c1b8ea23\" class=\"wlWriterEditableSmartContent\" style=\"margin: 0px;padding: 0px;float: none\">\n<pre> &lt;m:ImageFileListView x:Name=\"listView1\" ClipToBounds=\"False\" Grid.ColumnSpan=\"2\" \/&gt;\n<\/pre>\n<p><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http:\/\/dunnhq.com --><\/p>\n<\/div>\n<h2>Impl\u00e9mentation de la couche Model<\/h2>\n<p>Les objets utilis\u00e9s doivent impl\u00e9menter l\u2019interface <strong>IImageFile<\/strong>. Si vous souhaitez g\u00e9rer une hi\u00e9rarchie (par exemple des r\u00e9pertoires) vous devez en plus utiliser l\u2019interface <strong>IParentItem<\/strong>.<\/p>\n<p>Voici un exemple d\u2019impl\u00e9mentation (disponible dans l\u2019exemple).<\/p>\n<h3>Exemple d\u2019impl\u00e9mentation pour g\u00e9rer des fichiers\u00a0 :<\/h3>\n<p>&nbsp;<\/p>\n<div id=\"scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:10c207ef-859e-423f-a3dd-23c3a7dfc121\" class=\"wlWriterEditableSmartContent\" style=\"margin: 0px;padding: 0px;float: none\">\n<pre>public class ImageFile: IImageFile\n{\n   public string FileName { get; set; }\n   public IParentItem Parent { get; set; }\n\n   public virtual bool IsAvailable\n   {\n       get \n       {\n           return File.Exists(FileName);\n       }\n   }\n\n   public virtual Stream LoadImage()\n   {\n       byte[] buffer = File.ReadAllBytes(FileName);\n       return new MemoryStream(buffer);\n   }\n\n   #region ICloneable Membres\n\n   public virtual object Clone()\n   {\n       ImageFile o = new ImageFile();\n       o.FileName = this.FileName;\n       return o;\n   }\n\n   #endregion\n}<\/pre>\n<p><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http:\/\/dunnhq.com --><\/p>\n<\/div>\n<p>&nbsp;<\/p>\n<h3>Exemple d\u2019impl\u00e9mentation pour g\u00e9rer les r\u00e9pertoires d\u2019un disque<\/h3>\n<p>&nbsp;<\/p>\n<div id=\"scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:5b5bbb74-3a74-46dc-b793-a5f1b99dc701\" class=\"wlWriterEditableSmartContent\" style=\"margin: 0px;padding: 0px;float: none\">\n<pre>public class ParentImageFile : ImageFile, IImageFile, IParentItem\n{\n   public override bool IsAvailable\n   {\n       get\n       {\n           return Directory.Exists(FileName);\n       }\n   }\n   \n   public override Stream LoadImage()\n   {\n       return null;\n   }\n\n   public List&lt;IImageFile&gt; ImageFiles { get; set; }\n\n   public override object Clone()\n   {\n       ImageFile clonedItem = null;\n       ParentImageFile o = new ParentImageFile();\n       o.FileName = this.FileName;\n       o.ImageFiles = new List&lt;IImageFile&gt;();\n       foreach (IImageFile item in this.ImageFiles)\n       {\n           clonedItem = item.Clone() as ImageFile;\n           clonedItem.Parent = o;\n           o.ImageFiles.Add(clonedItem);\n       }\n       return o;\n   }\n}<\/pre>\n<p><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http:\/\/dunnhq.com --><\/p>\n<\/div>\n<p>&nbsp;<\/p>\n<h2>Impl\u00e9mentation de la couche View-Model<\/h2>\n<p>Vous pouvez directement utiliser l\u2019h\u00e9ritage d\u2019un objet <strong>CustomImageFileViewModel.<\/strong><\/p>\n<p>Le lien entre la couche Model et la couche View-Model est r\u00e9alis\u00e9e par le code suivant :<\/p>\n<div id=\"scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:ea3c6217-b9c6-49a2-a404-2c19f4d7cd48\" class=\"wlWriterEditableSmartContent\" style=\"margin: 0px;padding: 0px;float: none\">\n<pre>namespace WpfListViewMVVMSample.ViewModel\n{\n    public class ImageFileViewModel: CustomImageFileViewModel\n    {\n        public override void CreateFromFileName(string imageFileName)\n        {\n            ImageFile = new ImageFile() { FileName = imageFileName };\n        }\n    }\n}<\/pre>\n<p><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http:\/\/dunnhq.com --><\/p>\n<\/div>\n<h2>Initialisation des comportements DragAndDrop dans la vue<\/h2>\n<h3>Initialisation<\/h3>\n<p>Dans l\u2019initialisation de la fen\u00eatre, sur la partie View\u00a0 :<\/p>\n<div id=\"scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:6a7788f1-eab2-4f27-b1dc-cd8fa6226725\" class=\"wlWriterEditableSmartContent\" style=\"margin: 0px;padding: 0px;float: none\">\n<pre>namespace WpfListViewMVVMSample\n{\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Interaction logic for MainWindow.xaml\n    \/\/\/ &lt;\/summary&gt;\n    public partial class MainWindow : Window\n    {\n  \n        public MainWindow()\n        {\n            InitializeComponent();\n            this.DataContext = new MainWindowViewModel();\n            DragDropManagerListBoxAdornerViewModel&lt;ImageFileViewModel&gt; dragDropManager\n                = new DragDropManagerListBoxAdornerViewModel&lt;ImageFileViewModel&gt;\n                (listViewImages.ImageFilesListBox);\n            dragDropManager.RegisterDragDropManagerOperation(\n                new DragDropManagerOperationTreeView&lt;ImageFileViewModel&gt;());\n\n        }       \n    }\n}\n<\/pre>\n<p><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http:\/\/dunnhq.com --><\/p>\n<\/div>\n<p>&nbsp;<\/p>\n<ul>\n<li>La vue initialise le ViewModel : (this.DataContext = new MainWindowViewModel)<\/li>\n<li>La vue initialise le DragDropManager avec l\u2019objet ViewModel (ImageFileViewModel) d\u00e9crit plus haut et indique que les actions de Glisser-D\u00e9placer interviendront sur la liste listViewImages<\/li>\n<li>Le dragdrop est initialis\u00e9 pour pouvoir g\u00e9rer une structure d\u2019arbre r\u00e9cursive.<\/li>\n<\/ul>\n<h2>Initialisation du ViewModel de la liste<\/h2>\n<p>Le viewModel d\u00e9rive naturellement de INotifyPropertyChanged et l\u2019on retrouve classiquement PropertyChangedEventHandler et RaisePropertyChanged.<\/p>\n<p>Pour notre interface, nous avons 3 propri\u00e9t\u00e9s :<\/p>\n<ul>\n<li>ImagesPath : La donn\u00e9e repr\u00e9sentant de la zone de texte du r\u00e9pertoire contenant les images<\/li>\n<li>_imagesFilesData : Les fichiers images (partiellement affich\u00e9es dans la liste)<\/li>\n<li>LoadFilesCommand : L\u2019action de rechargement des fichiers depuis le r\u00e9pertoire<\/li>\n<\/ul>\n<p>Voici le code source de MainWindowViewModel qui sera \u201cbind\u00e9\u201d sur la vue MainWindow<\/p>\n<div id=\"scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:e563ce4c-020a-4347-b044-4ae34e3dba3c\" class=\"wlWriterEditableSmartContent\" style=\"margin: 0px;padding: 0px;float: none\">\n<pre>namespace WpfListViewMVVMSample.ViewModel\n{\n    public class MainWindowViewModel : INotifyPropertyChanged\n    {\n        private ImageFileCollectionViewModel&lt;ImageFileViewModel&gt; _imagesFilesData;\n        private string _imagesPath;\n\n        public ICommand LoadFilesCommand { get; private set; }    \n        \n        public string ImagesPath\n        {\n            get { return _imagesPath; }\n            set\n            {\n                _imagesPath = value;\n                RaisePropertyChanged(\"ImagesPath\");\n            }\n        }\n\n        public ImageFileCollectionViewModel&lt;ImageFileViewModel&gt; ImagesFilesData\n        {\n            get\n            {\n                return _imagesFilesData;\n            }\n        }\n       \n        public MainWindowViewModel()\n        {\n          _imagesFilesData = new ImageFileCollectionViewModel&lt;ImageFileViewModel&gt;();\n          ImagesPath = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);\n          LoadFilesCommand = new SimpleDelegateCommand(\n                (x) =&gt; { InitImagesFilesDataWithDirectory(_imagesPath); });\n        }\n\n        private void InitImagesFilesDataWithDirectory(string directory)\n        {\n            var files = from file in Directory.GetFiles(directory, \"*.*\")\n                        where file.ToUpper().EndsWith(\".JPG\")\n                        select new ImageFileViewModel() \n                          {ImageFile = new ImageFile() {FileName = file} };\n            foreach (var img in files)\n            {\n               _imagesFilesData.AllImages.Add(img);\n            }\n        }\n\n        public event PropertyChangedEventHandler PropertyChanged;\n\n        private void RaisePropertyChanged(string propertyName)\n        {\n            if (PropertyChanged == null) return;\n            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));\n        }\n    }\n}\n<\/pre>\n<p><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http:\/\/dunnhq.com --><\/p>\n<\/div>\n<p><strong>LoadFilesCommand<\/strong> est initialis\u00e9 avec un<strong> SimpleDelegateCommand<\/strong> d\u00e9crit ci dessous. Il permet de lancer sous forme de delegate une action et de traiter ainsi le chargement de la liste depuis le texte saisi.<\/p>\n<p>SimpleDelegateCommand peut \u00eatre utilis\u00e9 pour n\u2019importe quelle action d\u2019une commande n\u00e9cessitant de personnaliser le \u201cexecute\u201d avec un d\u00e9l\u00e9gu\u00e9.<\/p>\n<div id=\"scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:1771dcea-d732-410f-8cd6-f6d973c2213c\" class=\"wlWriterEditableSmartContent\" style=\"margin: 0px;padding: 0px;float: none\">\n<pre>public class SimpleDelegateCommand: ICommand\n{\n   Action&lt;object&gt; _executeDelegate;\n\n\n   public SimpleDelegateCommand(Action&lt;object&gt; executeDelegate)\n   {\n       _executeDelegate = executeDelegate;\n   }\n\n   public void Execute(object parameter)\n   {\n       _executeDelegate(parameter);\n   }\n\n   public bool CanExecute(object parameter) \n   { \n       return true; \n   }\n\n   public event EventHandler CanExecuteChanged;\n}<\/pre>\n<p><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http:\/\/dunnhq.com --><\/p>\n<\/div>\n<h2>Binding des donn\u00e9es sur le XAML<\/h2>\n<p>Le code XAML n\u2019a plus qu\u2019\u00e0 r\u00e9cup\u00e9rer le binding de la zone de texte, de la commande du bouton et de la liste des fichiers :<\/p>\n<div id=\"scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:77493629-1242-42c1-9f66-a2f404ed857c\" class=\"wlWriterEditableSmartContent\" style=\"margin: 0px;padding: 0px;float: none\">\n<pre>&lt;Window x:Class=\"WpfListViewMVVMSample.MainWindow\"\n   xmlns=\"http:\/\/schemas.microsoft.com\/winfx\/2006\/xaml\/presentation\"\n   xmlns:x=\"http:\/\/schemas.microsoft.com\/winfx\/2006\/xaml\"\n   xmlns:m=\"clr-namespace:ImageFileListView.View;assembly=ImageFileListView\"\n   Title=\"MainWindow\" Height=\"350\" Width=\"525\"&gt;\n&lt;Grid&gt;\n   &lt;Border x:Uid=\"Border_1\" BorderBrush=\"#FF4355C1\" BorderThickness=\"2,2,2,2\" \n           CornerRadius=\"4,4,4,4\" Margin=\"8,60,2,8\"&gt;\n       &lt;m:ImageFileListView x:Name=\"listViewImages\" ClipToBounds=\"False\" \n           DataContext=\"{Binding ImagesFilesData}\" \/&gt;\n   &lt;\/Border&gt;\n   &lt;Button Content=\"Ok\" Height=\"23\" Margin=\"0,22,12,0\" Name=\"button1\" \n           VerticalAlignment=\"Top\" HorizontalAlignment=\"Right\" Width=\"95\" \n           Command=\"{Binding LoadFilesCommand}\"\/&gt;\n   &lt;TextBox Height=\"23\" Margin=\"12,22,113,0\" Name=\"textBox1\" VerticalAlignment=\"Top\" \n            Text=\"{Binding ImagesPath}\"\/&gt;\n&lt;\/Grid&gt;\n&lt;\/Window&gt;\n<\/pre>\n<p><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http:\/\/dunnhq.com --><\/p>\n<\/div>\n<h2>R\u00e9sultat<\/h2>\n<p><a href=\"http:\/\/www.bratched.com\/media\/C%C3%A9dric\/image_2532359689.png\"><img decoding=\"async\" loading=\"lazy\" style=\"border-width: 0px\" title=\"Application exemple avec une liste d'images simple\" src=\"http:\/\/dev.bratched.fr\/fr\/wp-content\/uploads\/sites\/2\/importedmedia\/blogmedia-image-thumb1545839196-png.png\" alt=\"Application exemple avec une liste d'images simple\" width=\"529\" height=\"354\" border=\"0\" \/><\/a><\/p>\n<h2>Ajout de la gestion des r\u00e9pertoires<\/h2>\n<p>Nous allons modifier l\u2019interface pour prendre en charge la gestion des r\u00e9pertoires par une case \u00e0 cocher. Lorsque la case sera coch\u00e9e, la liste contiendra les r\u00e9pertoires, lorsqu\u2019elle sera d\u00e9coch\u00e9e elle n\u2019affichera que les images.<\/p>\n<p>Pour cela nous ajoutons un balise CheckBox qui sera \u201cBind\u00e9\u201d sur une propri\u00e9t\u00e9 ViewModel: <strong>IsDirectory<\/strong><\/p>\n<div id=\"scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:eb09a84f-926b-484a-ae5c-ec3c7b57bfa0\" class=\"wlWriterEditableSmartContent\" style=\"margin: 0px;padding: 0px;float: none\">\n<pre>&lt;CheckBox Content=\"Directories\" Height=\"16\" HorizontalAlignment=\"Left\" \n                  Margin=\"20,50,0,0\" VerticalAlignment=\"Top\" \n                  IsChecked=\"{Binding IsDirectory}\" \/&gt;<\/pre>\n<p><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http:\/\/dunnhq.com --><\/p>\n<\/div>\n<p>Dans le <strong>MainWindowViewModel<\/strong>, nous ajoutons la propri\u00e9t\u00e9 <strong>IsDirectory<\/strong><\/p>\n<div id=\"scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:0797b1d2-bde3-4c06-a5c4-8407972e133a\" class=\"wlWriterEditableSmartContent\" style=\"margin: 0px;padding: 0px;float: none\">\n<pre>public bool IsDirectory\n{\n  get { return _isDirectory; }\n  set\n  {\n      _isDirectory = value;\n      RaisePropertyChanged(\"IsDirectory\");\n  }\n}<\/pre>\n<p><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http:\/\/dunnhq.com --><\/p>\n<\/div>\n<p>Dans la Commande du bouton OK, nous modifions l\u2019appel :<\/p>\n<div id=\"scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:964f8dd8-65f6-42d5-b6ac-fb154b2bd6d3\" class=\"wlWriterEditableSmartContent\" style=\"margin: 0px;padding: 0px;float: none\">\n<pre>public MainWindowViewModel()\n{\n_imagesFilesData = new ImageFileCollectionViewModel&lt;ImageFileViewModel&gt;();\nImagesPath = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);\nLoadFilesCommand = new SimpleDelegateCommand(\n      (x) =&gt; { InitImagesFilesDataWithDirectory(ImagesPath, IsDirectory); });\n}<\/pre>\n<p><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http:\/\/dunnhq.com --><\/p>\n<\/div>\n<p>&nbsp;<\/p>\n<p><strong>InitImagesFilesDataWithDirectory<\/strong> appelle soit<\/p>\n<ul>\n<li>la liste des images ou soit<\/li>\n<li>la liste des images avec les r\u00e9pertoires r\u00e9cursifs.<\/li>\n<\/ul>\n<p>Le code ne pr\u00e9sente pas d\u2019int\u00e9r\u00eat ici et se trouve dans l\u2019exemple.<\/p>\n<h2>R\u00e9sultat avec les r\u00e9pertoires<\/h2>\n<p><a href=\"http:\/\/www.bratched.com\/media\/C%C3%A9dric\/image51166770213.png\"><img decoding=\"async\" loading=\"lazy\" style=\"border-width: 0px\" title=\"Application M-V-VM exemple avec Liste en arbre de type TreeView\" src=\"http:\/\/dev.bratched.fr\/fr\/wp-content\/uploads\/sites\/2\/importedmedia\/blogmedia-image5-thumb690316920-png.png\" alt=\"Application M-V-VM exemple avec Liste en arbre de type TreeView\" width=\"529\" height=\"354\" border=\"0\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<h2>T\u00e9l\u00e9chargements et exemples<\/h2>\n<p>Voici le lien pour t\u00e9l\u00e9charger la solution avec le code source du projet et des tests unitaires<\/p>\n<p><a title=\"download http:\/\/www.bratched.com\/download\/WPFImageFileListView.zip\" href=\"http:\/\/www.bratched.com\/download\/WPFImageFileListView.zip\"><img decoding=\"async\" loading=\"lazy\" title=\"download32x32\" src=\"http:\/\/dev.bratched.fr\/fr\/wp-content\/uploads\/sites\/2\/importedmedia\/blogmedia-download32x32-b64acb5051597c4460f5796cc7975efe-gif.gif\" alt=\"download32x32\" width=\"32\" height=\"32\" border=\"0\" \/><\/a> <a title=\"Download http:\/\/www.bratched.com\/download\/WPFImageFileListView.zip\" href=\"\/download\/WPFImageFileListView.zip\">WPFImageFileListView.zip [449 ko]<\/a><\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction Les projets pr\u00e9c\u00e9dents ont \u00e9t\u00e9 red\u00e9coup\u00e9s afin de fournir 2 assemblies directement utilisable. Pour ceux qui souhaitent ajouter rapidement un treeview d\u2019images avec une gestion de Drag&amp;Drop (Voir les 4 pr\u00e9c\u00e9dents chapitres ) voici les \u00e9tapes de r\u00e9alisation. L\u2019exemple suivant montre comment r\u00e9aliser une application respectant l\u2019architecture M-V-VM avec les briques Drag and Drop [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6],"tags":[2,3,4,24,5,7,8],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/bratched.com\/fr\/wp-json\/wp\/v2\/posts\/484"}],"collection":[{"href":"https:\/\/bratched.com\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bratched.com\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bratched.com\/fr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/bratched.com\/fr\/wp-json\/wp\/v2\/comments?post=484"}],"version-history":[{"count":0,"href":"https:\/\/bratched.com\/fr\/wp-json\/wp\/v2\/posts\/484\/revisions"}],"wp:attachment":[{"href":"https:\/\/bratched.com\/fr\/wp-json\/wp\/v2\/media?parent=484"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bratched.com\/fr\/wp-json\/wp\/v2\/categories?post=484"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bratched.com\/fr\/wp-json\/wp\/v2\/tags?post=484"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}