2010-10-21 2 views
0

J'ai implémenté un glisser-déposer qui fonctionne principalement dans mon application Silverlight 4. Une fois que les utilisateurs ont déposé les formes sur la toile, j'ai voulu utiliser Size & Child Decorators. J'ai essayé d'implémenter l'exemple de code. Le code ci-dessous est la section de problème de beaucoup plus grande application.Recherche d'objets enfants dans l'objet ViewBox/Canvas

Xmal -

<ScrollViewer Grid.RowSpan="1" Grid.Row="2" Grid.ColumnSpan="2" Grid.Column="2" Name="scrollViewer"> 
    <Viewbox Margin="0" MinWidth="400" MinHeight="500" 
     HorizontalAlignment="Left" VerticalAlignment="Top" Name="ViewBoxTestBuild"> 
     <Canvas x:Name="Camera1Canvas" telerikDragDrop:RadDragAndDropManager.AllowDrop="True" 
      Width="1200" Height="768" MouseLeftButtonDown="Camera1Canvas_MouseLeftButtonDown"> 
      <Image x:Name="Camera1Image" Source="timemagadj.jpg" Canvas.ZIndex="-1" 
        HorizontalAlignment="Left" VerticalAlignment="Top" /> 
      <local:Three_Line_Graphic x:Name="threeLineEditTool" 
        HorizontalAlignment="Left" Canvas.Left="594" Canvas.Top="621" /> 
      <l:Adorner x:Name="adorn" Canvas.ZIndex="100" /> 
     </Canvas> 
    </Viewbox> 
</ScrollViewer> 

C# code -

private void Camera1Canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) 
     { 
      var sendingObj = sender as Canvas; 
      if (sendingObj == null) return; 
      foreach (UserControl l in VisualTreeHelper.FindElementsInHostCoordinates(e.GetPosition(null), sendingObj)) 
       { 
        if (l.Parent == Camera1Canvas) 
        { 
         adorn.AdornedElement = l as FrameworkElement; 
         adorn.adorned_MouseLeftButtonDown(l, e); 
         break; 
        } 
       } 
      base.OnMouseLeftButtonDown(e); 
     } 

Mon problème est que lorsque VisualTreeHelper.FindElementsInHostCoordinates est appelé événement de clic gauche de la souris, il retourne aucun élément lorsque je clique sur un objet. Je suis sûr que c'est un problème de mappage des coordonnées, mais comme c'est nouveau pour moi, je ne sais pas comment y remédier.

Répondre

0

Vous devez changer votre ligne VisualTreeHelper à

GeneralTransform transform = sendingObj.TransformToVisual(Application.Current.RootVisual); 
Point pnt = transform.Transform(e.GetPosition(sendingObj)); 
var elements = VisualTreeHelper.FindElementsInHostCoordinates(pnt,Application.Current.RootVisual); 
+0

Votre suggestion revient toujours pas d'éléments. –

+0

Edité pour montrer une autre manière. Le système de coordonnées SL est un peu génial et a plusieurs bizarreries. – Stephan

+0

qui a bien fonctionné avec une modification: "VisualTreeHelper.FindElementsInHostCoordinates (pnt, sendingObj);" –

2

Peut-être que dans votre cas, il n'y a pas besoin d'utiliser la méthode VisualTreeHelper.

Puisque vous contrôlez les éléments à l'intérieur de la toile et vous savez leur type, vous pouvez essayer quelque chose comme ceci:

private void Camera1Canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) 
    { 
     var sendingObj = sender as Canvas; 
     if (sendingObj == null) return; 
     foreach (UserControl l in sendingObj.Children) 
      { 
       var position = e.GetPosition(l); 
       var lArea = new Rect(0,0,l.ActualWidth,l.ActualHeight); 
       if (lArea.Contains(position)) 
       { 
        adorn.AdornedElement = l as FrameworkElement; 
        adorn.adorned_MouseLeftButtonDown(l, e); 
        break; 
       } 
      } 
     base.OnMouseLeftButtonDown(e); 
    } 

Ce qui est plus efficace que hit-test. Cependant, cela ne fonctionne que si les zones rectangulaires sont acceptables.

Si vous avez besoin de détecter des formes autres que des rectangles, vous pouvez utiliser ce qui suit, aussi longtemps que vous remplissez une toile avec des instances de UserControl:

private void Camera1Canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) 
    { 
     var sendingObj = sender as Canvas; 
     if (sendingObj == null) return; 

     var elements = VisualTreeHelper 
      .FindElementsInHostCoordinates(
       e.GetPosition(sendingObj), sendingObj); 

     foreach (var l in elements) 
     { 
      if (l is UserControl) 
      { 
       adorn.AdornedElement = l as FrameworkElement; 
       adorn.adorned_MouseLeftButtonDown(l, e); 
       break; 
      } 
     } 
     base.OnMouseLeftButtonDown(e); 
    } 
+0

J'aime cette réponse, je l'utiliserai à une date ultérieure. Merci. –