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 :

Binding sur une methode avec un argument dynamique?


Sujet :

Windows Presentation Foundation

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    284
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 284
    Points : 79
    Points
    79
    Par défaut Binding sur une methode avec un argument dynamique?
    Bonjour à tous,

    Je rencontre un petit problème qui doit être tout bête mais malheureusement je ne trouve pas de solution. Je vais prendre un exemple.

    Une ListBox liste mes utilisateurs, à chaque fois que j'en selectionne un je veux afficher son ID dans une textbox plus bas.
    => fonctionnement ok
    Code xml : 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
     
    <StackPanel>
        <ListBox x:Name="ListBoxAllUser" Width="200" Height="100" IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding Path=ListAllUser, Mode=OneTime}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock>
                            <TextBlock.Text>
                                <MultiBinding StringFormat="{}{0} {1}">
                                    <Binding Path="Lastname" />
                                    <Binding Path="Firstname" />
                                </MultiBinding>
                            </TextBlock.Text>
                    </TextBlock>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
     
        <TextBlock Text="{Binding Path=ListAllUser/Id, Mode=OneWay, StringFormat={}ID: {0}}" />
    </StackPanel>

    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
     
    public partial class Main : Window
    {
        public struct StructContext
        {
            public List<UserEntity> ListAllUser { get; set; }
        }
     
        public Main()
        {
            InitializeComponent();
            DataContext = new StructContext
            {
                ListAllUser = new BLL.Business().GetAllUser()
            };
        }
    }

    Par contre maintenant au lieu d'afficher l'ID je voudrais afficher le répertoire ce cet utilisateur. Hors celui ci ne possède pas cette propriété, c'est le principe. Je l'obtiens en passant l'id de l'utilisateur à une méthode.

    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
     
    public class UserEntity
    {
        public UserEntity()
        {
        }
     
        public UserEntity(long id, string lastname, string firstname)
        {
            Id = id;
            Lastname = lastname;
            Firstname = firstname;
        }
     
        public long Id { get; set; }
        public string Lastname { get; set; }
        public string Firstname { get; set; }
    }

    J'ai une méthode qui me donne ce répertoire
    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    public string GetDirectoryUser(long idUser)
    {
        //Le path (ici en dur) est sauvegardé dans un fichier xml.
        return @"c:\machine\chemin\" + idUser;
    }

    Comment pouvoir appeler cette méthode à partir de mon fichier xaml?

    J'ai regardé du côté de ObjectDataProvider mais je ne sais pas comment mis prendre:
    Code xml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    <Window.Resources>
            <ObjectDataProvider x:Key="BusinessInstance" ObjectType="{x:Type bll:Business}" MethodName="GetDirectoryUser">
            <!-- Si je ne déclare pas d'argument, j'ai une erreur, mais je ne peux pas mettre de binding ici  -->
            </ObjectDataProvider>
        </Window.Resources>

    Deux précision:
    - ma méthode et ma classe ne sont pas statique.
    - converter : à oublier.

    Si quelqu'un à une idée je suis preneur.
    Merci d'avance.

  2. #2
    Membre régulier
    Inscrit en
    Octobre 2005
    Messages
    62
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 62
    Points : 85
    Points
    85
    Par défaut
    Voici un exemple que je viens de faire qui fait ce que tu veux (mais n'aurait-il pas été mieux de rendre ta fonction statique, avec non pas un long mais un UserEntity comme paramètre ?).

    J'ai une première listview qui affiche les users.
    Le SelectedItem est bindé sur l'objectinstance pour que l'ODP sache sur quel objet appelé la méthode.

    Les SelectedValuePath et SelectedValue sont là pour modifier le paramètre de la fonction.


    Pour la 2ème listview qui affiche le retour de la fonction, je dois mettre l'ODP comme DataContext car l'ItemsSource ne supporte pas directement un ObjectDataProvider.

    Si tu ne comprends pas tout, n'hésite pas à demander

    Code XML : 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
        <Window.Resources>
            <ObjectDataProvider x:Key="ODP"
                                MethodName="GetDirectory">
                <ObjectDataProvider.MethodParameters>
                    <sys:Int64>0</sys:Int64>
                </ObjectDataProvider.MethodParameters>
            </ObjectDataProvider>
        </Window.Resources>
        <Grid>
            <ListView Height="118"
                      HorizontalAlignment="Left"
                      Margin="44,84,0,0"
                      Name="listView1"
                      ItemsSource="{Binding .}"
                      SelectedItem="{Binding Source={StaticResource ODP}, Path=ObjectInstance, BindsDirectlyToSource=True}"
                      SelectedValue="{Binding Source={StaticResource ODP}, Path=MethodParameters[0], BindsDirectlyToSource=True}"
                      SelectedValuePath="Id"
                      VerticalAlignment="Top"
                      Width="128">
                <ListView.View>
                    <GridView>
                        <GridViewColumn Header="Id"
                                        Width="30"
                                        DisplayMemberBinding="{Binding Id}" />
                    </GridView>
                </ListView.View>
            </ListView>
            <ListView Height="136"
                      HorizontalAlignment="Left"
                      Margin="242,63,0,0"
                      Name="listView2"
                      DataContext="{StaticResource ODP}"
                      ItemsSource="{Binding .}"
                      VerticalAlignment="Top"
                      Width="168">
            </ListView>
        </Grid>

  3. #3
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 753
    Points
    39 753
    Par défaut
    Tu pourrais utiliser un convertisseur exprès pour ça, qui prend en entrée l'ID de l'utilisateur et appelle la méthode GetDirectoryUser. Mais perso je suis pas fan de cette approche, j'aime pas trop mettre de la logique métier dans les convertisseurs...

    La meilleure approche serait d'utiliser le pattern MVVM (*) : plutôt que de binder directement sur le UserEntity, tu aurais une classe UserViewModel qui servirait d'adapteur entre la vue et le modèle. Et dans cette classe, tu pourrais mettre une propriété Directory qui appelerait la méthode GetDirectoryUser...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    private readonly UserEntity _user;
     
    ...
     
    public string Directory
    {
        get { return GetDirectoryUser(_user.Id); }
    }
    (*) Pour plus d'infos :
    - Article de Josh Smith sur MSDN (en anglais)
    - Tuto sur Developpez.com (en français)

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    284
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 284
    Points : 79
    Points
    79
    Par défaut
    @tomlev J'aimerai bien me pencher sur MVVM mais comme je débute en C# / WPF, c'est vrai que j'ai beaucoup de problème à résoudre en amont avant de complexifier à nouveau.
    Complexifier dans le sens où je vais rencontrer de nouveau problème si je veux respecter le MVVM, je pense par exemple au MessageBox.

    @SpazouUn grand merci.
    J'ai juste rajouter Mode="OneWay" dans le SelectedItem de ma listbox, sionon j'avais une erreur de convertion et rajouter ObjectType="{x:Type bll:Business}" dans l'ObjectDataProvider .
    Je vais abuser un peu de ta patiente car je ne comprend pas tout dans le code.

    1)ObjectDataProvider ODPQu'est ce que ça fait exactement? ça créer une instance de bll:Business, ou c'est plutôt comme si on exposer la signature de la methode GetDirectory de bll:Business

    2)SelectedItemSelectedItem="{Binding Source={StaticResource ODP}, Path=ObjectInstance, BindsDirectlyToSource=True}"
    SelectedValue="{Binding Source={StaticResource ODP}, Path=MethodParameters[0], BindsDirectlyToSource=True}"
    SelectedValuePath="Id"

    Alors là je suis perdu
    SelectedItem prend pour valeur la'instance de ODP, c'est bien ça?
    Je en comprends pas comment on peut assigner à SelectedItem une valeur de bll:Business alors que ma listbox est peuplé de UserEntity.

    BindsDirectlyToSource=True ==> je ne connais absolument pas ça et je n'ai jamais utilisé SelectedValue et SelectedValuePath

    Désolé^

  5. #5
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 753
    Points
    39 753
    Par défaut
    Citation Envoyé par takinelinfo Voir le message
    @tomlev J'aimerai bien me pencher sur MVVM mais comme je débute en C# / WPF, c'est vrai que j'ai beaucoup de problème à résoudre en amont avant de complexifier à nouveau.
    Ca peut sembler plus complexe au début, mais sur le long terme je dirais plutôt que ça simplifie...

    Citation Envoyé par takinelinfo Voir le message
    Complexifier dans le sens où je vais rencontrer de nouveau problème si je veux respecter le MVVM, je pense par exemple au MessageBox.
    Il y a des solutions qui marchent très bien pour afficher des MessageBox en MVVM... D'autre part tu n'es pas obligé d'appliquer le pattern de façon stricte, du moins au début, tu peux toujours faire un MessageBox.Show dans ton ViewModel.
    Et même sans appliquer vraiment MVVM, tu peux toujours créer un objet qui servira d'adapteur entre la vue et le modèle...

  6. #6
    Membre régulier
    Inscrit en
    Octobre 2005
    Messages
    62
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 62
    Points : 85
    Points
    85
    Par défaut
    J'étais parti du principe que ta méthode GetDirectoryUser faisait parti de UserEntity, méa culpa, je me suis trompé, c'est ta classe "Business" ?


    Je vais t'expliquer mieux mon code :
    Code xml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
        <Window.Resources>
            <ObjectDataProvider x:Key="ODP"
                                MethodName="GetDirectory">
                <ObjectDataProvider.MethodParameters>
                    <sys:Int64>0</sys:Int64>
                </ObjectDataProvider.MethodParameters>
            </ObjectDataProvider>
        </Window.Resources>
    Je déclare un ObjectDataProvider, qui va devoir travailler sur la méthode "GetDirectory", et qui aura un paramètre, que j'initialise à 0. Et je ne lui donne pas plus d'info.

    Code xml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
            <ListView [...]
                      SelectedItem="{Binding Source={StaticResource ODP}, Path=ObjectInstance, BindsDirectlyToSource=True}"
                      SelectedValue="{Binding Source={StaticResource ODP}, Path=MethodParameters[0], BindsDirectlyToSource=True}"
                      SelectedValuePath="Id"

    SelectedItem : tu dois le voir autrement, je n'affecte pas à SelectedItem la valeur de l'ObjectDataProvider, mais l'inverse, j'affecte à l'ObjectInstance ce que l'utilisateur va sélectionner.
    L'ObjectDataProvider ayant pour fonction de "retourner" quelque chose, il ne faut pas que le binding cherche "ObjectInstance" sur ce que retourne l'ODP, mais directement sur l'ODP, d'où le "BindDirectlyToSource".

    En affectant ObjectInstance, l'ObjectDataProvider trouve tout seul le ObjectType, et la méthode GetDirectoryUser qui lui est associé.

    Ensuite, il faut envoyer l'Id de ce qui est sélectionné à l'ODP. Comme ce n'est pas faisable en un seul binding, je "triche" en demandant à la ListView de mettre l'Id de l'objet sélectionné dans SelectedValue, et le SelectedValue je le "renvoie" sur l'ODP avec un binding.


    Normalement, ça ne devait effectivement pas marcher chez toi, un UserEntity n'étant pas un Business, mais l'ObjectDataProvider a forcé le cast, et comme dans ta fonction GetDirectoryUser tu ne fais rien qui touche à ton objet, ça ne plante pas.

    Tu devrais chercher comment arriver à affecter un vrai objet Business à l'ObjectInstance de ton ObjectDataProvider, ou alors passe ta fonction en statique. Car tu ne nous donnes pas de code expliquant où et comment tu te sert de cette classe, donc je ne peux pas t'aider plus.
    Ou alors faire une VM comme l'a dit tomlev

Discussions similaires

  1. Axis2 : exposer une methode avec comme argument String[][]
    Par Morbo dans le forum Services Web
    Réponses: 2
    Dernier message: 23/09/2009, 10h32
  2. Réponses: 9
    Dernier message: 09/12/2008, 00h07
  3. Binding sur une propriété avec paramètre
    Par FRED.G dans le forum Windows Presentation Foundation
    Réponses: 1
    Dernier message: 17/11/2008, 18h38
  4. passage d'une methode avec argument
    Par skanderb dans le forum JSF
    Réponses: 27
    Dernier message: 27/04/2007, 17h36
  5. Réponses: 3
    Dernier message: 09/08/2006, 11h58

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