Sto costruendo un controllo canvas. Questa tela radice ha diversi bambini sovrapposti (anche tela). Questo è fatto in modo che ogni bambino possa gestire il proprio disegno e io posso quindi comporre il risultato finale con qualsiasi combinazione di bambini per ottenere il comportamento desiderato.C# wpf controlli sovrapposti che non ricevono gli eventi del mouse
Questo funziona molto bene per quanto riguarda il rendering. Tuttavia, questo non funziona molto bene con gli eventi del mouse. Le opere Eventi modo del mouse sono i seguenti (utilizzando PreviewMouseMove come esempio):
1- Se tela radice è sotto il mouse, evento fuoco 2- Controllare tutti i bambini, se uno è sotto il mouse, evento fuoco e fermare
Come tale, solo il primo figlio che aggiungo riceverà l'evento di spostamento del mouse. L'evento non viene propagato a tutti i bambini perché si sovrappongono.
Per ovviare a questo, ho cercato i seguenti: 1- Ignora gli eventi del mouse nella tela radice 2- Per ogni evento, trovare tutti i bambini che vogliono gestire l'evento utilizzando VisualTreeHelper.HitTest 3- Per tutti i bambini che ha restituito un risultato di hit test valido (es .: sotto il mouse e disposto a gestire l'evento (IsHitTestVisible == true)), ???
Questo è il punto in cui sono bloccato, in qualche modo devo inviare l'evento del mouse a tutti i bambini e interrompere il normale flusso dell'evento per accertarmi che il primo figlio non lo riceva due volte (tramite handled = true nel evento).
Utilizzando RaiseEvent con lo stesso evento trasmesso ai bambini, le cose sembrano funzionare ma in qualche modo solleva l'evento sul genitore (tela principale). Per bypassare questo ho avuto bisogno di creare una copia dell'evento e impostare la forza per impostare la fonte anche se sembra essere più un hack che una soluzione. Esiste un modo corretto per fare ciò che sto cercando di fare? Segue l'esempio di codice.
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;
}
Si noti che avrò anche bisogno di questo per lavorare con le descrizioni dei comandi all'interno dei figli dei figli della tela radice. –
E 'questo per Silverlight? WPF? Aggiungi i tag pertinenti, otterrai una risposta più veloce. – SirDemon