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 :

Une vue pour les contrôler tous


Sujet :

Windows Presentation Foundation

  1. #1
    Membre à l'essai
    Inscrit en
    Mars 2012
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : Mars 2012
    Messages : 19
    Points : 10
    Points
    10
    Par défaut Une vue pour les contrôler tous
    Bonjour,

    Sous ce titre quelque peu racoleur, j'ai 2 questions simples.
    Est il "conforme" d'avoir 1 seule vue pour plusieurs ViewModel et comment transmettre à cette vue les bonnes données selon le ViewModel utilisé?


    Car voici mon dilemme.
    Je dois afficher des coordonnées de nos clients (nom, prénom, adresse etc...) pour :
    -celui que l'on livre
    -celui qui nous paye

    Les champs à afficher sont identiques pour les 2, seules les données peuvent peuvent être différentes.
    Dans mon esprit, une unique vue est donc nécessaire.


    Je parviens parfaitement à afficher ma vue pour plusieurs ViewModel, mais je ne sais pas binder les données...



    Voici ce que j'ai fait (en simplifiant, j'espère que ça restera compréhensible).
    J'ai crée une fenêtre principale qui affichera 2 boutons (sous forme de listbox dynamique), "livré à" et "payeur" :

    Code : 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
    <UserControl x:Class="Discovery.View.BaseInfoView"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:ViewModel="clr-namespace:ViewModel"
                 xmlns:View="clr-namespace:Discovery.View">
     
        <UserControl.Resources>
            <DataTemplate DataType="{x:Type ViewModel:ShipToViewModel}">
                <View:CustomerInfoView />
            </DataTemplate>
            <DataTemplate DataType="{x:Type ViewModel:SoldToViewModel}">
                <View:CustomerInfoView />
            </DataTemplate>
        </UserControl.Resources>
     
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="40"/>
                <RowDefinition />
            </Grid.RowDefinitions>
     
            <ListBox Grid.Row="0" Name="LstCustomerInfo" ItemsSource="{Binding SubMenus}" SelectedIndex="0">
                <ListBox.ItemsPanel>
                    <ItemsPanelTemplate>
                        <StackPanel Orientation="Horizontal"/>
                    </ItemsPanelTemplate>
                </ListBox.ItemsPanel>
     
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Name}" Padding="10" VerticalAlignment="Center"/>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
     
            <GroupBox Grid.Row="1">
                <ContentControl Content="{Binding ElementName=LstCustomerInfo, Path=SelectedItem}"/>
            </GroupBox>
        </Grid>
    </UserControl>

    Fenêtre contrôlée par un ViewModel :

    Code : 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
    namespace ViewModel
    {
        class BaseInfoViewModel : BaseViewModel
        {
            public override string Name 
            {
                get { return "Info de base"; } 
            }
     
     
            private readonly ObservableCollection<BaseViewModel> _submenus;
            public ObservableCollection<BaseViewModel> SubMenus
            {
                get { return this._submenus; }
            }
     
     
     
            public BaseInfoViewModel()
            {
                this._submenus = new ObservableCollection<BaseViewModel>();
     
                this._submenus.Add(new ShipToViewModel());
                this._submenus.Add(new SoldToViewModel());
            }
        }
    }

    Les 2 ViewModel :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    namespace ViewModel
    {
        public class ShipToViewModel : BaseViewModel
        {
            public override string Name
            {
                get { return "Livré à "; }
            }
        }
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    namespace ViewModel
    {
        class SoldToViewModel : BaseViewModel
        {
            public override string Name
            {
                get { return "Payeur"; }
            }
        }
    }

    Et un UserControl devant afficher toutes les coordonnées :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    <UserControl x:Class="Discovery.View.CustomerInfoView"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
        <Grid>
            <TextBlock Text="Nom : " />
            <TextBlock Text="{Binding Name1, Mode=OneWay}" />
        </Grid>
    </UserControl>

    Les Model utilisés sont ceux ci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    namespace Model
    {
        public class DiscoveryModel
        {
            public string ID { get; set; }
            public string Qualification { get; set; }
            public CustomerInfo ShipTo { get; set; }
            public CustomerInfo Soldto { get; set; }
        }
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    namespace Model
    {
        public class CustomerInfo
        {
            public string Name1 { get; set; }
            public AddressModel Address { get; set; }
            public string Email { get; set; }
            public string Phone { get; set; }
        }
    }


    Maintenant je suis coincé, je ne sais pas comment indiquer à ma vue qu'un coup il faut prendre le "livré à" et l'autre le "payeur". Il doit falloir changer le DataContext selon le ViewModel utilisé, mais je ne sais pas comment faire.


    Je m'en remet donc à votre science

    Merci.

  2. #2
    Expert confirmé

    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2010
    Messages
    2 065
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2010
    Messages : 2 065
    Points : 4 229
    Points
    4 229
    Par défaut
    Pourquoi tu ne fais pas 2 vues mais qui pointe sur le même template, ça te simplifiera les choses.

  3. #3
    Membre à l'essai
    Inscrit en
    Mars 2012
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : Mars 2012
    Messages : 19
    Points : 10
    Points
    10
    Par défaut
    Merci de m'avoir lu.


    Pour simplifier la compréhension, je n'ai indiqué que le "livré à" et le "payeur".
    J'ai aussi le "facturé à", "commandé par" et je risque d'en avoir d'autres.

    Une seule vue gérée par plusieurs ViewModel m'allait très bien

  4. #4
    Expert confirmé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2009
    Messages
    2 025
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2009
    Messages : 2 025
    Points : 5 462
    Points
    5 462
    Par défaut
    Je comprends pas pourquoi tu as besoin de 2 view models différents s'il s'agit d'un même objet ( en gros une adresse à chaque fois ).
    Le problème d'avoir la même vue c'est que si des noms sont différents dans les view models alors les bindings ne fonctionneront pas. Si tu es sûr d'avoir les même noms& types, c'est donc qu'il s'agit du même view model!

  5. #5
    Membre à l'essai
    Inscrit en
    Mars 2012
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : Mars 2012
    Messages : 19
    Points : 10
    Points
    10
    Par défaut
    Je pense que vous avez raison, mais je ne sais pas comment faire.

    Pour être plus concret, voici ce que je souhaite refaire
    Nom : disco1.png
Affichages : 220
Taille : 26,2 Ko


    C'est une fenêtre comportant un TabControl.
    Je souhaite que chaque TabItem soit composé d'un UserControl car ca sera plus simple à modifier/gérer.

    Le 1er TabItem est "Information de Base", ce sera un UserControl et il comportera 4 boutons "livré à", "vendu à", "facturé à" et "payeur".
    Sous ces boutons, en encadré rouge, ira un autre UserControl que je souhaiterai être unique pour afficher les coordonnées selon le bouton cliqué.

    Par ex, le bouton "vendu à" ressemblera à ceci :
    Nom : Disco2.png
Affichages : 268
Taille : 24,0 Ko


    Je n'ai pas trouvé d'autre moyen que de passer par 1 ViewModel par bouton pour afficher un UserControl :
    Code : 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
    <UserControl x:Class="Discovery.View.Discovery_BaseInfoView"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:ViewModel="clr-namespace:ViewModel"
                 xmlns:View="clr-namespace:Discovery.View">
     
        <UserControl.Resources>
            <DataTemplate DataType="{x:Type ViewModel:Discovery_ShipToViewModel}">
                <View:Discovery_CustomerInfoView />
            </DataTemplate>
            <DataTemplate DataType="{x:Type ViewModel:Discovery_SoldToViewModel}">
                <View:Discovery_CustomerInfoView />
            </DataTemplate>
        </UserControl.Resources>
     
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="40"/>
                <RowDefinition />
            </Grid.RowDefinitions>
     
            <ListBox Grid.Row="0" Name="LstCustomerInfo" ItemsSource="{Binding SubMenus}" SelectedIndex="0">
                <ListBox.ItemsPanel>
                    <ItemsPanelTemplate>
                        <StackPanel Orientation="Horizontal"/>
                    </ItemsPanelTemplate>
                </ListBox.ItemsPanel>
     
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Name}" Padding="10" VerticalAlignment="Center"/>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
     
            <GroupBox Grid.Row="1">
                <ContentControl Content="{Binding ElementName=LstCustomerInfo, Path=SelectedItem}"/>
            </GroupBox>
        </Grid>
    </UserControl>
    Grâce à cela, j'affiche ici 2 boutons et lorsque je clique sur l'un, ca affiche le UserControl que je souhaite via les DataTemplate en ressources.
    Le problème c'est comment lui passer les bonnes données.



    Il y a peut être une autre façon de faire et dans ce cas, je veux bien que l'on m'aiguille

  6. #6
    Expert confirmé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2009
    Messages
    2 025
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2009
    Messages : 2 025
    Points : 5 462
    Points
    5 462
    Par défaut
    Je te propose une description de code je n'ai pas le temps pour du vrai.

    L'idée c'est d'avoir dans ton BaseInfoView 2 propriétés de type CustomerInfo (enfin tu le nommes comme tu veux ce sont toutes les infos d'un payeur/acheteur). Ainsi que deux propriétés de type bool : IsShipVisible et IsSoldVisible.

    Dans BaseInfoView tu instancies 2 usercontrols CustomerInfoView,que tu bindes sur chacun de tes CustomerInfo (tu les superposes dans une grille, ou tu les mets dans un stackpanel pour débug, peu importe...) et dont tu bindes également la propriété "Visible" sur le IsShipVisible/IsSoldVisible (avec un converter BoolToVisibility).

    Le clique sur l'un des boutons (par commande donc puisque tu utilises MVVM) va simplement te permettre de mettre en vrai/faux les IsShipVisible/IsSoldVisible. Regardes également les CanExecute des commandes de manière à avoir tes boutons grisés en fonction du mode courant.

    Edit: Finalement puisqu'il s'agit de la même vue tu peux également n'utiliser qu'une seule vue que tu bindes sur une propriété du style CurrentCustomerInfo.
    Tes boutons ne feront que mettre à jour ce CurrentCustomerInfo (il faut être sûr d'avoir implémenté InotifyPropertyChanged) avec la bonne instance du CustomerInfo!

  7. #7
    Membre à l'essai
    Inscrit en
    Mars 2012
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : Mars 2012
    Messages : 19
    Points : 10
    Points
    10
    Par défaut
    Avant de lire ta réponse j'ai parcouru quelques forums et ait trouvé hier soir un semblant de réponse.
    Je n'ai pas encore tester ta réponse.


    Je me suis inspiré de cet article de John Smith pour trouver mon bonheur.



    Voici ce que j'ai fait.
    Dans le ViewModel ci dessous, j'appelle le constructeur de base en précisant mon objet. Je passe cet objet aux ViewModel "fils" (shipto et soldto)
    Code : 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
    namespace ViewModel
    {
        class Discovery_BaseInfoViewModel : Discovery_ViewModelBase
        {
            public override string DisplayName 
            {
                get { return "Info de base"; } 
            }
    
    
            private readonly ObservableCollection<Discovery_ViewModelBase> _submenus;
            public ObservableCollection<Discovery_ViewModelBase> SubMenus
            {
                get { return this._submenus; }
            }
    
    
            public Discovery_BaseInfoViewModel(DiscoveryModel Discovery)
                : base (Discovery)
            {
                this._submenus = new ObservableCollection<Discovery_ViewModelBase>();
                
                this._submenus.Add(new Discovery_ShipToViewModel(Discovery));
                this._submenus.Add(new Discovery_SoldToViewModel(Discovery));
            }
        }
    }

    Dans les ViewModel Shipto/SoldTo, j'ajoute une propriété Cust qui renvoi le "bon" client :
    Code : 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
    namespace ViewModel
    {
        public class Discovery_ShipToViewModel : Discovery_ViewModelBase
        {
            public override string DisplayName
            {
                get { return "Livré à "; }
            }
    
    
            public CustomerInfo Cust
            {
                get{ return base.Discovery.ShipTo; }
            }
    
    
            public Discovery_ShipToViewModel(DiscoveryModel Discovery)
               : base (Discovery)
            {
            }
        }
    }

    Le ViewModel SoldTo renverra base.Discovery.SoldTo.
    Le ViewModel Payer renverra base.Discovery.Payer.
    Etc...



    Et dans me vue unique, je bind toutes les propriétes de mes clients de la façon suivante : Cust.xxxx.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <UserControl x:Class="Discovery.View.Discovery_CustomerInfoView"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
        <Grid>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="Nom : " />
                <TextBlock Text="{Binding Cust.Name1, Mode=OneWay}" />
            </StackPanel>
        </Grid>
    </UserControl>


    Voila.
    Je tente de regarder ce que tu m'as indiqué d'ici peu.

Discussions similaires

  1. Grid : Une row pour les remplir tous x)
    Par Arnard dans le forum Windows Presentation Foundation
    Réponses: 3
    Dernier message: 04/03/2013, 09h57
  2. Réponses: 10
    Dernier message: 26/03/2008, 22h37
  3. Utulisation d'une table pour les jointure ( probleme )
    Par Boumeur dans le forum Langage SQL
    Réponses: 8
    Dernier message: 11/04/2005, 15h21
  4. Créer une vue pour trier une requete UNION ?
    Par Etienne Bar dans le forum SQL
    Réponses: 3
    Dernier message: 03/01/2003, 20h22

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