Drag and Drop entre ListView et TextBox

Drag and Drop entre ListView et TextBox - C#/.NET managed - Programmation

Marsh Posté le 06-07-2016 à 17:47:06    

Salut à tous,
Je viens vers vous car je n'arrive pas à trouver une réponse simple à mon problème.
Je voudrais, comme le titre l'indique, prendre un item de ma listview et le déposer dans ma textbox.
(Plus complètement je voudrais afficher dans la textbox le nom qu'il y a sur mon item et dans le Tag placer l'ID référencé avec)
Pour être plus clair je vais coller mon code...
 
Voici ma MainPage :
 

Code :
  1. <Page
  2.     x:Class="DragDropTest.MainPage"
  3.     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  4.     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  5.     xmlns:local="using:DragDropTest"
  6.     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  7.     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  8.     xmlns:data="using:DragDropTest.Models"
  9.     mc:Ignorable="d">
  10.     <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
  11.         <Grid.ColumnDefinitions>
  12.             <ColumnDefinition Width="*"/>
  13.             <ColumnDefinition Width="4*"/>
  14.         </Grid.ColumnDefinitions>
  15.         <ListView Name="myLV" ItemsSource="{x:Bind Persons}" CanDrag="True" DragItemsStarting="ListView_DragItemsStarting" CanDragItems="True">
  16.             <ListView.ItemTemplate>
  17.                 <DataTemplate x:DataType="data:Person">
  18.                     <StackPanel Orientation="Horizontal">
  19.                         <Image Width="48" Source="{x:Bind Image}"/>
  20.                         <StackPanel Orientation="Vertical">
  21.                             <TextBlock Text="{x:Bind Name}"/>
  22.                             <TextBlock Text="{x:Bind LastName}"/>
  23.                         </StackPanel>
  24.                     </StackPanel>
  25.                 </DataTemplate>
  26.             </ListView.ItemTemplate>
  27.         </ListView>
  28.         <StackPanel Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center">
  29.             <TextBlock Text="Nom"/>
  30.             <TextBox Name="myTB" AllowDrop="True" DragOver="myTB_DragOver" Drop="myTB_Drop"/>
  31.         </StackPanel>
  32.     </Grid>
  33. </Page>


 
Son code behind :
 

Code :
  1. namespace DragDropTest
  2. {
  3.     /// <summary>
  4.     /// Une page vide peut être utilisée seule ou constituer une page de destination au sein d'un frame.
  5.     /// </summary>
  6.     public sealed partial class MainPage : Page
  7.     {
  8.         private List<Person> Persons;
  9.         public MainPage()
  10.         {
  11.             this.InitializeComponent();
  12.             Persons = PersonManager.GetPerson();
  13.         }
  14.         private void ListView_DragItemsStarting(object sender, DragItemsStartingEventArgs e)
  15.         {
  16.            
  17.         }
  18.         private void myTB_DragOver(object sender, DragEventArgs e)
  19.         {
  20.             e.AcceptedOperation = DataPackageOperation.Copy;
  21.             e.DragUIOverride.Caption = "Poser ici";
  22.             e.DragUIOverride.IsCaptionVisible = true;
  23.             e.DragUIOverride.IsContentVisible = true;
  24.             e.DragUIOverride.IsGlyphVisible = true;
  25.         }
  26.         private async void myTB_Drop(object sender, DragEventArgs e)
  27.         {
  28.            
  29.         }
  30.     }
  31. }


 
et ma classe Person :
 

Code :
  1. namespace DragDropTest.Models
  2. {
  3.     public class Person
  4.     {
  5.         public int ID { get; set; }
  6.         public string Name { get; set; }
  7.         public string LastName { get; set; }
  8.         public string Image { get; set; }
  9.     }
  10.     public class PersonManager
  11.     {
  12.         public static List<Person> GetPerson()
  13.         {
  14.             var persons = new List<Person>();
  15.             persons.Add(new Person { ID = 1, Name = "Joe", LastName = "Smith", Image = "Assets/male-01.png" });
  16.             persons.Add(new Person { ID = 2, Name = "Albert", LastName = "Martin", Image = "Assets/male-02.png" });
  17.             persons.Add(new Person { ID = 3, Name = "Claudine", LastName = "David", Image = "Assets/female-01.png" });
  18.             return persons;
  19.         }
  20.     }
  21. }


 
Mon but étant que lors du déposer dans ma textBox, le prénom et le nom s'affiche dans la textBox et l'id se place dans la propriété Tag (si c'est possible bien sur!)
J'ai essayé plain de chose mais rien n'y fait !
 
Merci d'avance pour votre aide.
Nico

Reply

Marsh Posté le 06-07-2016 à 17:47:06   

Reply

Marsh Posté le 08-07-2016 à 10:20:22    

Vraiment personne ne peut m'aider ?

Reply

Marsh Posté le 10-07-2016 à 10:51:02    

Si :o
Pour un truc sensé être super puissant et faciliter la vie moi je trouve ça lourd le drag drop en UAP.

 

Voilà un truc qui fait exactement ce que tu demandes, j'ai modifié deux méthodes de ton exemple :

Code :
  1. private void ListView_DragItemsStarting(object sender, DragItemsStartingEventArgs e)
  2.         {
  3.             Person person = ((Person)e.Items[0]);
  4.             e.Data.SetText(person.ID + "-" + person.LastName + " " + person.Name);
  5.         }
  6.   private async void myTB_Drop(object sender, DragEventArgs e)
  7.         {
  8.             if (e.DataView.Contains(StandardDataFormats.Text))
  9.             {
  10.                 var def = e.GetDeferral();
  11.                 var s = await e.DataView.GetTextAsync();
  12.                 string id = s.Substring(0, s.IndexOf('-'));
  13.                 string name = s.Substring(s.IndexOf('-') + 1);
  14.                 myTB.Text = name;
  15.                 myTB.Tag = id;
  16.                 e.AcceptedOperation = DataPackageOperation.Copy;
  17.                 def.Complete();
  18.             }
  19.         }
 

L'idée c'est qu'au moment du Drag tu enregistres dans le DataPackage lié à l'événement le truc à emmener, et tu le récupères lors du Drop.

 

Là j'ai utilisé du Text et un bricolage à base de split pour passer l'id et le nom.
En théorie DataPackage a aussi une méthode SetData, mais je ne sais pas l'utiliser pour des objets Custom ( :na: ), mais on trouve des exemples sur Internet.
Mon exemple ne permet de dropper qu'un seul élément à la fois, mais c'est ce que tu veux apparemment.

 

Il y a peut être d'autre façons de faire (genre récupérer l'objet droppé avec les données qui ont servi à le binder) mais celle la fonctionne.


Message édité par TotalRecall le 10-07-2016 à 10:54:08

---------------
Topic .Net - C# @ Prog
Reply

Marsh Posté le 10-07-2016 à 14:21:22    

Merci TotalRecall !! :bounce:  
J'allais poster une solution moins "propre" mais qui fonctionne pour moi :
J'ai créé une variable de "transfert" :

Code :
  1. Person myP;


Au niveau du drag je l'ai mis sur le StackPanel du DataTemplate plutôt que sur la Listview elle même et j'ai fait la méthode suivante :

Code :
  1. private void myLV_DragStarting(UIElement sender, DragStartingEventArgs args)
  2.         {
  3.             var senderElement = sender as FrameworkElement;
  4.             myP = (Person)senderElement.DataContext;
  5.         }


Et au niveau du Drop je recopie les valeurs de ma variable (dans mon projet finale il y aura plusieurs TextBox et du coup le Drop me permet de savoir ou copier mes infos) :

Code :
  1. private void myTB_Drop(object sender, DragEventArgs e)
  2.         {
  3.             myTB.Text = myP.Name;
  4.             myTB.Tag = myP.ID;
  5.             myP = null;
  6.         }


 
C'est pas le plus correct mais pour moi ça fonctionne !!
Merci encore.
Nico

Reply

Marsh Posté le 11-07-2016 à 11:44:54    

C'est sale (variable privée utilisée juste pour ça et ça ne suit pas le modèle de développement suggéré par MS) mais ça marche aussi tant que tu ne gères pas des dizaines de drag drop entre des tas de contrôles différents :D
Fais juste quelques nulls check (ex : actuellement je pense que si on vient dropper sur ta textbox un truc qui vient de n'importe où, genre le bureau, ton programme explose en vol)


Message édité par TotalRecall le 11-07-2016 à 11:46:09

---------------
Topic .Net - C# @ Prog
Reply

Marsh Posté le 12-07-2016 à 21:04:41    

J'avais prévu de mettre des sécurités un peu partout. La mon code est très simplifié pour aller plus vite ! :D  
En tout cas encore merci pour ton aide. Je vais poster une autre question pour un autre petit problème. Mais celui ci est "réglé" !

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed