2015-08-27 19 views
13

Nella mia app, un utente può selezionare uno Image e trascinarlo su un Grid, per giocare con esso. Lo faccio gestendo l'evento PointerEntered dello Grid. Qui rilevo se l'utente ha selezionato un'immagine e se l'utente sta tenendo premuto il pulsante del mouse.Let image ManipulationMode capture pointer

Ora voglio mettere il Image sulla griglia, e passare il puntatore (ancora premuto) al mio Image, in modo che il Image utilizza il proprio ManipulationStarted, ManipulationDelta e ManipulationCompleted eventi. Questo dovrebbe consentire all'utente di trascinare l'immagine con un movimento fluido dall'elenco di immagini a Grid, invece di dover rilasciare e fare clic sull'elemento.

ho cercato rilasciando il puntatore dalla sender in PointerEntered, e catturare utilizzando CapturePointer, ma questo non sembra funzionare, anche se i rendimenti CapturePointertrue.

ecco il codice che uso per il PointerEntered evento:

private void DrawingArea_OnPointerEntered(object sender, PointerRoutedEventArgs e) 
{ 
    // If we enter the grid while dragging and we have an image that was dragged 
    if (e.Pointer.IsInContact && CurrentDraggedImage != null) 
    { 
     DrawingArea.Children.Add(CurrentDraggedImage); 

     // Move it to the location we're currently at 
     var transform = (CurrentDraggedImage.RenderTransform as CompositeTransform); 
     transform.TranslateX += e.GetCurrentPoint(DrawingArea).RawPosition.X - DrawingArea.ActualWidth/2; 
     transform.TranslateY += e.GetCurrentPoint(DrawingArea).RawPosition.Y - DrawingArea.ActualHeight/2; 

     // This works (I think) 
     (sender as UIElement).ReleasePointerCaptures(); 
     // This doesn't work (or it isn't what I need), but returns true 
     CurrentDraggedImage.CapturePointer(e.Pointer); 

     // Get ready for a new image 
     CurrentDraggedImage = null; 
    } 
} 

Il mio codice manipolazione è in questa risposta:

https://stackoverflow.com/a/32230733/1009013

+0

Avete considerato un approccio diverso: utilizzare CanDragItems incorporato da ListView e impostare AllowDrop come vero nell'area di disegno? –

+0

@JustinXL No, ma suppongo che questo dia lo stesso posto di blocco ... lo controllerò e tornerò da te. – vrwim

+0

@JustinXL sì, lo stesso problema, non posso spostare il puntatore da un'azione di trascinamento all'altra ... – vrwim

risposta

0

Perché non basta usare il drag-N- far cadere? Creare una griglia contenente la vostra barra degli strumenti (ad esempio, un elenco di immagini per trascinare) e una griglia di destinazione che risponde a dragdrop comandi:

<Grid> 

    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="Auto" /> 
     <ColumnDefinition Width="Auto" /> 
     <ColumnDefinition /> 
    </Grid.ColumnDefinitions> 

    <ListBox Background="AliceBlue" MouseMove="OnMouseMove"> 

     <ListBox.Resources> 
      <Style TargetType="{x:Type Image}"> 
       <Setter Property="Width" Value="64" /> 
       <Setter Property="Height" Value="64" /> 
      </Style> 
     </ListBox.Resources> 

     <Image Source="http://www.wpclipart.com/recreation/games/chess/chess_set_1/chess_piece_white_pawn_T.png" /> 
     <Image Source="http://www.wpclipart.com/recreation/games/chess/chess_set_1/chess_piece_white_rook_T.png" /> 
     <Image Source="http://www.wpclipart.com/recreation/games/chess/chess_set_1/chess_piece_white_knight_T.png" /> 
     <Image Source="http://www.wpclipart.com/recreation/games/chess/chess_set_1/chess_piece_white_bishop_T.png" /> 
     <Image Source="http://www.wpclipart.com/recreation/games/chess/chess_set_1/chess_piece_white_queen_T.png" /> 
     <Image Source="http://www.wpclipart.com/recreation/games/chess/chess_set_1/chess_piece_white_king_T.png" /> 
     <Image Source="http://www.wpclipart.com/recreation/games/chess/chess_set_1/chess_piece_black_pawn_T.png" /> 
     <Image Source="http://www.wpclipart.com/recreation/games/chess/chess_set_1/chess_piece_black_rook_T.png" /> 
     <Image Source="http://www.wpclipart.com/recreation/games/chess/chess_set_1/chess_piece_black_knight_T.png" /> 
     <Image Source="http://www.wpclipart.com/recreation/games/chess/chess_set_1/chess_piece_black_bishop_T.png" /> 
     <Image Source="http://www.wpclipart.com/recreation/games/chess/chess_set_1/chess_piece_black_queen_T.png" /> 
     <Image Source="http://www.wpclipart.com/recreation/games/chess/chess_set_1/chess_piece_black_king_T.png" /> 
    </ListBox> 

    <GridSplitter Grid.Column="1" Width="5" Background="LightGray" /> 

    <Grid x:Name="targetGrid" Grid.Column="2" AllowDrop="True" DragEnter="OnDragEnter" DragOver="OnDragMove" DragLeave="OnDragLeave" Drop="OnDrop" Background="Transparent"/> 

</Grid> 

tua casella di riepilogo ha bisogno di un gestore di MouseMove per rilevare quando un'immagine viene trascinato e i gestori di comando semplicemente rispondere ai vari eventi come richiesto, la clonazione richiedono dell'immagine e trascinandoli attraverso la faccia della griglia di conseguenza:

public partial class MainWindow : Window 
{ 
    private Image DragImage = null; 

    public MainWindow() 
    { 
     InitializeComponent(); 
    } 

    private void OnMouseMove(object sender, MouseEventArgs e) 
    { 
     // make sure we have an image 
     var image = e.OriginalSource as Image; 
     if (image == null) 
      return; 

     // make sure we've started dragging 
     if (e.LeftButton != MouseButtonState.Pressed) 
      return; 

     DragDrop.DoDragDrop(image, image, DragDropEffects.Copy); 
    } 

    private void OnDragEnter(object sender, DragEventArgs e) 
    { 
     // make sure we have an image 
     if (!e.Data.GetDataPresent(typeof(Image)))   
     { 
      e.Effects = DragDropEffects.None; 
      return; 
     } 

     // clone the image 
     var image = e.Data.GetData(typeof(Image)) as Image; 
     e.Effects = DragDropEffects.Copy; 
     this.DragImage = new Image { Source = image.Source, Width=64, Height=64 }; 
     var position = e.GetPosition(this.targetGrid); 
     this.DragImage.SetValue(Grid.MarginProperty, new Thickness(position.X-32, position.Y-32, 0, 0)); 
     this.DragImage.SetValue(Grid.HorizontalAlignmentProperty, HorizontalAlignment.Left); 
     this.DragImage.SetValue(Grid.VerticalAlignmentProperty, VerticalAlignment.Top); 
     this.DragImage.IsHitTestVisible = false; // so we don't try and drop it on itself 

     // add it to the target grid 
     targetGrid.Children.Add(this.DragImage); 
    } 

    private void OnDragMove(object sender, DragEventArgs e) 
    { 
     var position = e.GetPosition(this.targetGrid); 
     this.DragImage.SetValue(Grid.MarginProperty, new Thickness(position.X - 32, position.Y - 32, 0, 0)); 
    } 

    private void OnDragLeave(object sender, DragEventArgs e) 
    { 
     targetGrid.Children.Remove(this.DragImage); 
     this.DragImage = null; 
    } 


    private void OnDrop(object sender, DragEventArgs e) 
    { 
     this.DragImage.IsHitTestVisible = true; 
     this.DragImage = null; 
    } 

} 

risultati:

enter image description here

Ho fatto l'orribile e brutto modo WPF qui invece di MVVM pulito ed elegante, ma tu hai l'idea. Inoltre non capisco perché vuoi trascinare le cose su una griglia anziché su una tela?

+0

Sto solo tornando a questo problema, e ora proverò a fare il drag and drop in modo civile (al momento tocca ad aggiungere). Ricordo di aver usato una griglia perché non conoscevo la tela e molti altri elementi non sembravano essere la scelta giusta o non consentivano più bambini. – vrwim

+0

L'ho implementato ora usando Drag & Drop, UWP non sembra avere il 'DragDrop.DoDragDrop', quindi ho dovuto usare' CanDragItems'. Inoltre, il tuo modo di catturare 'OnMouseMove' non funziona su UWP, in quanto il ListView acquisisce quello da scorrere (l'applicazione arriva su un tablet). – vrwim