IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Windows Presentation Foundation Discussion :

Ajouter des controls a une window WPF


Sujet :

Windows Presentation Foundation

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Mai 2006
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 14
    Par défaut Ajouter des controls a une window WPF
    Hello tout le monde,

    Suis nouveau en ce qui concerne WPF. Ca a l'air carrement terrible d'apres tout ce que j'en lis sur le net mais je dois surement l'aborder du mauvais cote parce que je suis a 2 doigts d'en etre degouter et de ne plus vouloir en entendre parler.

    Ce que je souhaite faire ne parait pourtant pas insurmontable :

    Lorsque j'ouvre mon application qui ne comporte qu'une seule window, je voudrais qu'au chargement ou a l'evenement X, creer autant de bouton qu'il y a d'executable dans un repertoire definit en dur dans le code et les afficher dans ma window.

    En gros, si je definit mon repertoire comme etant celui d'insallation d'Office , je vais retrouver tous les executable word, excel, access etc... et les afficher sous forme de bouton dans ma fenetre.

    C'est pourtant bete hein ? Mais je ne sais absolument pas par ou commencer.

    Si quelqu'un aurait ne serait-ce que des pistes pour demarrer ca serait sympa. J'ai deja lu les 60 page du tuto dispo ici : http://morpheus.developpez.com/windo...on-foundation/

    mais j'ai pas trouver ca tres clair. Il y a bien ces quelque ligne de code xaml a la page 10 :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    <Button Name="m_BoutonMirroir" VerticalAlignment="Top" HorizontalAlignment="Center" Width="200" Height="100">
    <Image Source="{Binding Source=Images/WinFX.jpg}" />
    </Button>
    C'est exactement ca que je veux pouvoir faire, mais de facon dynamique...


    Merci d'avance...

  2. #2
    Membre averti
    Inscrit en
    Mai 2006
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 14
    Par défaut
    Ok, j'ai u peu avance. Je posterais des que j'aurais une solution "propre" si jamais quelqu'un en a besoin.

  3. #3
    Membre Expert Avatar de davcha
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 258
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 258
    Par défaut
    Tu t'y prends mal, je pense.

    Il ne faut pas chercher à manipuler la hiérarchie des éléments d'interface WPF directement.
    C'est effectivement une excellente façon d'dégoûter par cette technologie, pour la bonne raison que ça n'est pas conçu pour fonctionner de cette façon.

    Ton interface WPF (juste le code xaml) se veut purement descriptif : t'es pas vraiment censé avoir de processus de création de bouton, d'image, ou autre, comme tu cherches à le faire ici.
    Tu dois plutôt chercher à décrire quand, comment et quoi générer en fonction de quelles données.

    En pratique, tu vas avoir un objet (un ViewModel) qui servira de DataContext (t'as dû en entendre parler ?), qui va fournir des données à ton interface WPF. Et cette dernière va se "brancher" à ces données via ce qu'on appelle des Bindings.

    Dans ton cas, pour l'affichage d'un bouton contenant une image pour chaque exécutable d'un répertoire, tu auras un objet qui va lister les fichiers exécutables du répertoire souhaité, qui leur associera peut-être également une image personnalisée pour chaque exécutable.
    Ensuite, ton ViewModel va interroger cet objet afin de fournir une collection d'objets (généralement une ObservableCollection<T>), sur laquelle se branchera ton interface WPF (ta view).

    Au niveau de ta view, tu auras dans ton code xaml un contrôle implémentant la propriété ItemsSource (une ListBox, ListView, ItemsControl, StackPanel, FlowPanel, etc...) sur laquelle tu vas binder ta propriété ObservableCollection<T> de ton ViewModel. Cela va permette de décrire quelles sont les données utilisées pour générer ton interface.

    A côté de ça, ton contrôle implémentant ItemsSource aura sa propriété ItemTemplate définie avec un DataTemplate décrivant comment tes données devront êtres présentées.
    Dans ton cas, ça ressemblera à ça :
    Code xaml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    <DataTemplate>
      <Button VerticalAlignment="Top" HorizontalAlignment="Center" Width="200" Height="100">
        <Image Source="{Binding ExecutableImagePath}" />
      </Button>
    </DataTemplate>

    Et là, t'as terminé. Le framework prend en charge le reste.


    Pour plus d'infos, renseigne-toi sur le pattern MVVM.

  4. #4
    Membre averti
    Inscrit en
    Mai 2006
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 14
    Par défaut
    Euh... OK.

    Bon ca veut dire que je vais recommencer en implementant cette methode alors.
    Merci pour ton aide. Je pense que j'aurais surement d'autres questions sous peu

  5. #5
    Membre averti
    Inscrit en
    Mai 2006
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 14
    Par défaut
    Bon, apres avoir regarder des heures de videos sur MVVM, lu des dizaines d'articles sur le net.... Pu...n c'que c'est lourd et complexe pour finalement si "peu" de chose (relativement a ce que je veux faire bien sur). Le resultat final poutre a mort mais faut le meriter.

    Pour le moment j'ai reussi a afficher ma fenetre avec mes boutons et mes images en utilisant un bout de code chiner sur le net (ici). C'est moche et ca plante quand je veux changer mon container d'une listview vers un wrapgrid. Et le wrapgrid ne contient pas de propriete "itemsource" (tant pis pour moi, je trouvais ca pas mal).

    En gros, une fois de plus il faut que je recommence from scratch. Je suis entrain de jeter un oeil aux framework MVVM sans grande conviction. Est-ce que ca me simplifira vraiment les choses ? Ou mon appli est tellement basique qu'un framework est inutile ?

    La suite bientot avec de meilleures nouvelles j'espere (si je ne me suis pas pendu entre temps)...

  6. #6
    Membre Expert Avatar de davcha
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 258
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 258
    Par défaut
    T'as pas choisi l'exemple le plus simple, c'est clair.
    Par exemple, les dependencyproperties dans un viewmodel, j'éviterais personnellement. Je réserve ça plutôt pour les usercontrols.

    En réalité c'est beaucoup plus simple que ce qu'il y a sur ton lien, et c'est également beaucoup plus simple que de taper dans le code de l'ui, comme tu le ferais en winforms.

    Je te mets un petit exemple :

    MainViewModel.cs :
    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
    using System;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.IO;
     
    namespace WpfApplication1
    {
        class MainViewModel : INotifyPropertyChanged
        {
            #region INotifyPropertyChanged Implementation
            public event PropertyChangedEventHandler PropertyChanged;
            void OnPropertyChanged(string propertyName)
            {
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
            #endregion
     
            string _path;
            bool _allDirectories;
     
            public string Path
            {
                get { return _path; }
                set
                {
                    if (value != _path)
                    {
                        _path = value;
                        RefreshExecutableFiles();
                        OnPropertyChanged("Path");
                    }
                }
            }
            public bool AllDirectories
            {
                get { return _allDirectories; }
                set
                {
                    if (value != _allDirectories)
                    {
                        _allDirectories = value;
                        RefreshExecutableFiles();
                        OnPropertyChanged("AllDirectories");
                    }
                }
            }
     
            public ObservableCollection<ExecutableFile> ExecutableFiles { get; private set; }
     
            public MainViewModel()
            {
                ExecutableFiles = new ObservableCollection<ExecutableFile>();
                Path = Environment.CurrentDirectory;
            }
     
            void RefreshExecutableFiles()
            {
                try
                {
                    ExecutableFiles.Clear();
                    foreach (var file in Directory.GetFiles(Path, "*.exe",
                        AllDirectories
                        ? SearchOption.AllDirectories
                        : SearchOption.TopDirectoryOnly))
                    {
                        ExecutableFiles.Add(new ExecutableFile(file));
                    }
                }
                catch
                {
                }
            }
     
            public void Show()
            {
                new MainWindow { DataContext = this }
                    .Show();
            }
        }
    }

    ExecutableFile.cs :
    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
    using System.Diagnostics;
    using System.Linq;
    using System.Windows.Input;
     
    namespace WpfApplication1
    {
        /// <summary>
        /// Pas besoin d'implémenter INotifyPropertyChanged,
        /// car les objets ExecutableFile sont immutables.
        /// </summary>
        class ExecutableFile
        {
            public ExecutableFile(string file)
            {
                Name = file.Split('\\').Last();
                Path = file;
                ExecuteCommand = new Command
                {
                    ExecuteDelegate = x => Process.Start(Path)
                };
            }
     
            public string Name { get; private set; }
            public string Path { get; private set; }
            public ICommand ExecuteCommand { get; private set; }
        }
    }

    Command.cs :
    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
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows.Input;
     
    namespace WpfApplication1
    {
        class Command : ICommand
        {
            public Func<object, bool> CanExecuteDelegate { get; set; }
            public Action<object> ExecuteDelegate { get; set; }
     
            public bool CanExecute(object parameter)
            {
                if (CanExecuteDelegate != null)
                    return CanExecuteDelegate(parameter);
                return true;
            }
     
            public event EventHandler CanExecuteChanged
            {
                add { CommandManager.RequerySuggested += value; }
                remove { CommandManager.RequerySuggested -= value; }
            }
     
            public void Execute(object parameter)
            {
                if (ExecuteDelegate != null)
                    ExecuteDelegate(parameter);
            }
        }
    }

    MainWindow.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
    <Window x:Class="WpfApplication1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <Label Content="Path"/>
            <TextBox Text="{Binding Path}" Grid.Column="1"/>
            <ItemsControl ItemsSource="{Binding ExecutableFiles, UpdateSourceTrigger=PropertyChanged}" Grid.ColumnSpan="2" Grid.Row="1">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <WrapPanel IsItemsHost="True"/>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <Button Content="{Binding Name}" Command="{Binding ExecuteCommand}"/>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </Grid>
    </Window>

    App.xaml
    Code xaml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    <Application x:Class="WpfApplication1.App"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    </Application>

    App.xaml.cs :
    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
    using System.Windows;
     
    namespace WpfApplication1
    {
        /// <summary>
        /// Logique d'interaction pour App.xaml
        /// </summary>
        public partial class App : Application
        {
            protected override void OnStartup(StartupEventArgs e)
            {
                base.OnStartup(e);
     
                new MainViewModel().Show();
            }
        }
    }

    Si tu as des question, n'hésites pas.

  7. #7
    Membre éprouvé Avatar de titourock
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2008
    Messages
    156
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2008
    Messages : 156
    Par défaut
    Hello,

    Je me permets de me joindre à la discussion
    Citation Envoyé par Billy GunZ Voir le message
    Pu...n c'que c'est lourd et complexe pour finalement si "peu" de chose (relativement a ce que je veux faire bien sur).
    Essayant d'appliquer du mieux que je peux et ayant mis du temps à comprendre (du moins je le comprends bien mieux qu'au début) on peut penser que le MVVM est un pattern lourd. Je pense qu'il n'en ait rien bien au contraire. Ce pattern permet de vraiment structurer le développement en "rendant à la vue ce qui est à la vue".

    La vue étant là pour afficher et gérer des évènements propres à l'affichage (effet visuels), le MVVM ne dit rien d'autre que : "On déclare ce qu'on doit afficher et on délègue toute la partie interaction utilisateur (cliques par exemple) à une autre entité". Et cette "entité"...c'est le ViewModel (modèle de la vue) qui permet de gérer les actions utilisateurs avec des ICommand comme te l'a montré davcha pour faire des traitements métiers à l'aide de ton Modèle.

    La puissance de cette architecture réside dans le Binding. On veut afficher une liste d'éléments ? On utilise un ItemsControl (listbox ou listview par exemple) dont on binde sa source de données sur la liste en question (ou plus exactement sur une vue de cette collection). On veut relier le clique sur un bouton à un traitement ? On binde la propriété "Command" de celui-ci sur une ICommand du ViewModel...

    La vue ne voit ainsi que le ViewModel qui ne voit lui-même que le Model. Le ViewModel est donc un "adaptateur WPF" de ton Model dans le sens où ton modèle peut très bien exister au départ pour un autre type de technologie (WinForms par exemple...)

    A ce propros
    public void Show()
    {
    new MainWindow { DataContext = this }
    .Show();
    }
    ne me semble pas bonne car là, le ViewModel "voit" la vue ce qui est contraire au principe énoncé auparavant.

    Il ne faut enfin pas perdre de vue que tout ce que tu gagnes en simplicité immédiate (moins de conception) se ressentira plus tard en terme de maintenance et d'évolutivité...

    Pour la compréhension du MVVM il y un bon article sur développez ici

    Pour bien le comprendre, commence à l'aide d'exemples plus simples comme binder une commande (cela peut paraître idiot mais il y a de quoi faire...) et pour te faciliter la tâche tu as aussi le site de Josh Smith maître en la matière...

    En espérant que cela puisse t'aider.

Discussions similaires

  1. Ajouter des controles dans une gridview
    Par IAmByB dans le forum ASP.NET
    Réponses: 1
    Dernier message: 28/11/2012, 22h51
  2. ajouter des controles sur une autre form
    Par kineton dans le forum Windows Forms
    Réponses: 4
    Dernier message: 06/10/2009, 10h32
  3. [Listview]Ajout Name des controles d'une form dans une listview
    Par Roken62 dans le forum Windows Forms
    Réponses: 3
    Dernier message: 12/01/2009, 13h17
  4. [WPF] Ajouter des UsersControls dans une Window
    Par jacpapac dans le forum Windows Presentation Foundation
    Réponses: 9
    Dernier message: 12/12/2008, 18h03
  5. ajouter des control dans une onglet de sstab sous VB6
    Par aymane_farissi dans le forum VB 6 et antérieur
    Réponses: 3
    Dernier message: 26/09/2005, 13h44

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo