2009-08-27 14 views
7

Ho un evento indirizzato dichiarati come tali (i nomi sono stati cambiati per proteggere gli innocenti):WPF - Gestione degli eventi collegati personalizzato su controlli personalizzati

public class DragHelper : DependencyObject { 
    public static readonly RoutedEvent DragCompleteEvent = EventManager.RegisterRoutedEvent(
     "DragComplete", 
     RoutingStrategy.Bubble, 
     typeof(DragRoutedEventHandler), 
     typeof(DragHelper) 
    ); 

    public static void AddDragCompleteHandler(DependencyObject dependencyObject, DragRoutedEventHandler handler) { 
     UIElement element = dependencyObject as UIElement; 
     if (element != null) { 
      element.AddHandler(DragCompleteEvent, handler); 
     } 
    } 

    public static void RemoveDragCompleteHandler(DependencyObject dependencyObject, DragRoutedEventHandler handler) { 
     UIElement element = dependencyObject as UIElement; 
     if (element != null) { 
      element.RemoveHandler(DragCompleteEvent, handler); 
     } 
    } 

roba piuttosto standard. In XAML, ho un DataTemplate che contiene un singolo controllo personalizzato. Sto tentando di collegare questo evento (così come alcune altre proprietà associate) per il controllo:

<DataTemplate ...> 
    <My:CustomControl 
     My:DragHelper.IsDragSource="True" 
     My:DragHelper.DragComplete="DragCompleteHandler" /> 
</DataTemplate> 

questo non riesce a produrre i risultati desiderati. In particolare, mentre viene chiamato il codice che chiama RaiseEvent() per l'evento DragComplete, il gestore non viene mai richiamato. Né, in effetti, sono i gestori di altri eventi instradati personalizzati che sono collegati altrove in questo file XAML.

Ho provato a cambiare il nome dell'evento indirizzato e ho provato a passare il modello dati da uno a DataType a uno con x: Key. Questo non ha prodotto alcun cambiamento visibile nel comportamento.

Tuttavia, se cambio My: CustomControl a qualsiasi controllo WPF incorporato, ad esempio un TextBlock, gli eventi vengono generati esattamente come vorrei. Allo stesso modo, se sostituisco il mio controllo personalizzato con qualsiasi altra sottoclasse UserControl personalizzata dal mio progetto, il comportamento ritorna allo stato non gestito, senza eventi mai creato.

Questo non ha molto senso per me. C'è qualcosa di specifico che devo fare per far funzionare questo scenario? Sembra che non dovrebbe importare. Suppongo sia possibile che ci sia una cosa specifica che ho fatto in tutti i miei controlli personalizzati che causa la rottura della gestione degli eventi, ma non ho visto nulla di comune nei tre o quattro controlli personalizzati che ho provato finora.

risposta

1

Non hai pubblicato tutto il codice, quindi ho dovuto dedurre e mettere insieme la mia versione. Funziona bene per me. Forse confrontare e contrapporre al codice:

Window1.xaml.cs:

using System.Windows; 
using System.Windows.Controls; 

namespace WpfApplication1 
{ 
    public partial class Window1 : Window 
    { 
     public Window1() 
     { 
      InitializeComponent(); 
     } 

     private void DragCompleteHandler(object sender, RoutedEventArgs e) 
     { 
      MessageBox.Show("YEP"); 
     } 
    } 

    public class CustomControl : TextBox 
    { 
    } 

    public class DragHelper : DependencyObject 
    { 
     public static readonly DependencyProperty IsDragSourceProperty = DependencyProperty.RegisterAttached("IsDragSource", 
      typeof(bool), 
      typeof(DragHelper), 
      new FrameworkPropertyMetadata(OnIsDragSourceChanged)); 

     public static bool GetIsDragSource(DependencyObject depO) 
     { 
      return (bool)depO.GetValue(IsDragSourceProperty); 
     } 

     public static void SetIsDragSource(DependencyObject depO, bool ids) 
     { 
      depO.SetValue(IsDragSourceProperty, ids); 
     } 

     public static readonly RoutedEvent DragCompleteEvent = EventManager.RegisterRoutedEvent(
      "DragComplete", 
      RoutingStrategy.Bubble, 
      typeof(RoutedEventHandler), 
      typeof(DragHelper) 
     ); 

     public static void AddDragCompleteHandler(DependencyObject dependencyObject, RoutedEventHandler handler) 
     { 
      UIElement element = dependencyObject as UIElement; 
      if (element != null) 
      { 
       element.AddHandler(DragCompleteEvent, handler); 
      } 
     } 

     public static void RemoveDragCompleteHandler(DependencyObject dependencyObject, RoutedEventHandler handler) 
     { 
      UIElement element = dependencyObject as UIElement; 
      if (element != null) 
      { 
       element.RemoveHandler(DragCompleteEvent, handler); 
      } 
     } 

     private static void OnIsDragSourceChanged(DependencyObject depO, DependencyPropertyChangedEventArgs e) 
     { 
      (depO as TextBox).TextChanged += delegate 
      { 
       (depO as TextBox).RaiseEvent(new RoutedEventArgs(DragCompleteEvent, null)); 
      }; 
     } 
    } 
} 

Window1.xaml:

<Window x:Class="WpfApplication1.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:WpfApplication1" 
    Title="Window1" Height="300" Width="300"> 
    <Window.Resources> 
     <DataTemplate x:Key="Test"> 
      <local:CustomControl 
       local:DragHelper.IsDragSource="True" 
       local:DragHelper.DragComplete="DragCompleteHandler" /> 
     </DataTemplate> 
    </Window.Resources> 

    <ContentControl ContentTemplate="{StaticResource Test}"/> 
</Window> 
+0

Grazie. Il controllo personalizzato è derivato da UserControl, ma anche il passaggio a TextBox come il tuo presenta ancora il problema per me. Ho omesso il resto del codice perché è fondamentalmente uguale al tuo, ad eccezione di alcune modifiche al namespace. Tuttavia, fa parte di un progetto molto più ampio, quindi potrebbe esserci un qualche tipo di interazione con uno stile o una risorsa globale o qualcosa di cui non sono a conoscenza potrebbe avere un impatto sul problema. Vedrò cosa posso fare. –

+1

Va bene, quindi mi sono ingannato un po '. Partendo dal tuo esempio completo, che ha funzionato per me, ho provato varie cose per trasformarlo nel caso non funzionale che sto vedendo nel mio progetto più ampio. Dopo un po ', sono incappato in una semplice modifica al codice base che riproduce il problema. Se prendo la tua implementazione DragHelper e la sposto in un altro assembly a cui fa riferimento l'applicazione principale e modifichiamo Window1.xaml di conseguenza (aggiungi un xmlns: altro e user altro: invece di local :) poi non vedo più la finestra del messaggio fire quando scrivo la casella di testo. : | –

Problemi correlati