c# wpf chevauchement des contrôles de ne pas recevoir les événements de la souris

Je suis la construction d'un contrôle de zone de dessin. Cette racine toile a plusieurs chevauchement des enfants (de la toile). Ceci est fait de sorte que chaque enfant peut gérer son propre dessin et je peux composez ensuite le résultat final avec tous les enfants pour obtenir le comportement souhaité.

Cela fonctionne très bien autant que le rendu est concerné. Cela ne fonctionne pas si bien avec les événements de la souris. La façon dont les événements de la souris œuvres sont comme suit (en utilisant previewmousemove à titre d'exemple):

1 - Si la racine de la toile est sous la souris, le feu de l'événement
2 - Vérifier tous les enfants, si l'on est sous la souris, le feu de l'événement et arrêter

En tant que tel, seul le premier enfant, j'ai ajouter recevrez le déplacement de la souris de l'événement. L'événement n'est pas propagée à tous les enfants, parce qu'ils se chevauchent.

Pour remédier à cela, j'ai tenté le suivant:
1 - Remplacer les événements de la souris dans la racine de la toile
2 - Pour chaque événement, tous les enfants qui veulent gérer l'événement à l'aide de VisualTreeHelper.HitTest
3 - Pour tous les enfants qui ont retourné un valide frappé résultat du test (c'est à dire: en vertu de la souris et prêt à gérer l'événement (IsHitTestVisible == true)), ???

C'est là que je suis bloqué, j'ai en quelque sorte besoin d'envoyer l'événement de la souris à tous les enfants, et d'arrêter le flux normal de l'événement pour s'assurer le premier enfant de ne pas recevoir deux fois (via traitées = true dans le cas).

En utilisant RaiseEvent avec le même événement se passa sur les enfants, les choses semblent fonctionner mais de toute façon il déclenche l'événement sur le parent (racine de la toile). Pour contourner cela, j'avais besoin de créer une copie de l'événement et de l'ensemble de la force de définir la source même s'il semble être plus un hack qu'une solution. Est-il une bonne façon de faire ce que je suis en train de faire? Exemple de Code qui suit.

    public class CustomCanvas : Canvas
{
private List<object> m_HitTestResults = new List<object>();
public new event MouseEventHandler MouseMove;
public CustomCanvas()
{
base.PreviewMouseMove += new MouseEventHandler(CustomCanvas_MouseMove);
}
private void CustomCanvas_MouseMove(object sender, MouseEventArgs e)
{
//Hack here, why is the event raised on the parent as well???
if (e.OriginalSource == this)
{
return;
}
Point pt = e.GetPosition((UIElement)sender);
m_HitTestResults.Clear();
VisualTreeHelper.HitTest(this,
new HitTestFilterCallback(OnHitTest),
new HitTestResultCallback(OnHitTest),
new PointHitTestParameters(pt));
MouseEventArgs tmpe = new MouseEventArgs(e.MouseDevice, e.Timestamp, e.StylusDevice);
tmpe.RoutedEvent = e.RoutedEvent;
tmpe.Source = this;
foreach (object hit in m_HitTestResults)
{
UIElement element = hit as UIElement;
if (element != null)
{
//This somehow raises the event on us as well as the element here, why???
element.RaiseEvent(tmpe);
}
}
var handlers = MouseMove;
if (handlers != null)
{
handlers(sender, e);
}
e.Handled = true;
}
private HitTestFilterBehavior OnHitTest(DependencyObject o)
{
UIElement element = o as UIElement;
if (element == this)
{
return HitTestFilterBehavior.ContinueSkipSelf;
}
else if (element != null && element.IsHitTestVisible && element != this)
{
return HitTestFilterBehavior.Continue;
}
return HitTestFilterBehavior.ContinueSkipSelfAndChildren;
}
private HitTestResultBehavior OnHitTest(HitTestResult result)
{
//Add the hit test result to the list that will be processed after the enumeration.
m_HitTestResults.Add(result.VisualHit);
//Set the behavior to return visuals at all z-order levels.
return HitTestResultBehavior.Continue;
}
Notez que j'ai également besoin de ce travail avec les info-bulles à l'intérieur des enfants des enfants de la racine de la toile.
Est-ce pour silverlight? WPF? Ajouter des tags pertinents, vous obtiendrez une réponse plus rapide.

OriginalL'auteur | 2009-04-11