Estoy creando un control canvas. Este lienzo raíz tiene varios elementos superpuestos (lienzos también). Esto se hace para que cada niño pueda manejar su propio dibujo y luego puedo componer el resultado final con cualquier combinación de niños para obtener el comportamiento deseado.controles superpuestos C# wpf que no reciben eventos de mouse
Esto está funcionando muy bien en lo que respecta a la representación. Sin embargo, esto no funciona tan bien con los eventos del mouse. Los trabajos acontecimientos manera ratón son los siguientes (utilizando PreviewMouseMove como ejemplo):
1- Si la lona de la raíz está en ratón, caso de incendio 2- Comprobar todos los niños, si uno está bajo el ratón, caso de incendio y detener
Como tal, solo el primer hijo que agregue recibirá el evento de mover el mouse. El evento no se propaga a todos los niños porque se superponen.
Para superar esto, me trataron los siguientes: 1- eventos de ratón Override en el lienzo de la raíz 2- Para cada evento, encontrar todos los niños que quieren controlar el evento usando VisualTreeHelper.HitTest 3- Para todos los niños que devolvió un resultado válido de la prueba de aciertos (es decir: bajo el mouse y dispuesto a manejar el evento (IsHitTestVisible == true)), ???
Aquí es donde estoy atascado, de alguna manera tengo que enviar el evento del mouse a todos los niños, y detener el flujo normal del evento para asegurarme de que el primer hijo no lo reciba dos veces (mediante handle = true en evento).
Al usar RaiseEvent con el mismo evento pasado a los niños, las cosas parecen funcionar, pero de alguna manera también se plantea el evento en el elemento principal (lienzo raíz). Para eludir esto, necesitaba crear una copia del evento y configurar la fuerza para establecer el origen, aunque parece ser más un hack que una solución. ¿Hay una forma adecuada de hacer lo que estoy tratando de hacer? El ejemplo del código sigue.
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;
}
Tenga en cuenta que también necesitaré esto para trabajar con información sobre herramientas dentro de hijos de hijos del lienzo raíz. –
¿Esto es para Silverlight? WPF? Agregue las etiquetas relevantes, obtendrá una respuesta más rápido. – SirDemon