2010-02-22 15 views
8

Immagina la situazione in cui apri un WPF Popup (ad esempio tramite ButtonClick). Hai uno ListBox direttamente nello Popup con alcuni elementi, quindi devi essere in grado di scorrere. Immagina che questo sia il tuo Custom Control e si trovi nello ScrollViewer.WPF rileva genitore scorrevole Controllo

Ora se ci si sposta con il mouse fuori dalla superficie Popup e si scorre, cosa succede? Si scorre su e giù ma con lo Popup aperto! E questo è il problema

La domanda è, come rilevare dall'interno del controllo, che qualche altro controllo padre sconosciuto nel VisualTree ha iniziato a scorrere? e impostare consecutivamente IsDropDownOpen = false?

+0

Ho la stessa domanda e problema. Scorro la mia griglia e il mio popup con operazioni personalizzate rimane nello stesso posto! Ho bisogno di scorrere popup con la griglia! – Evgeny

risposta

10

Possiamo scrivere un trigger per l'utilizzo con elementi contenuti in uno ScrollViewer. Qui è un'applicazione di esempio completo:

<Grid> 
    <ScrollViewer VerticalAlignment="Top" Height="200"> 
     <StackPanel HorizontalAlignment="Left"> 
      <Button Name="button" Content="Open"> 
       <i:Interaction.Triggers> 
        <i:EventTrigger EventName="Click"> 
         <ei:ChangePropertyAction TargetObject="{Binding ElementName=popup}" PropertyName="IsOpen" Value="True"/> 
        </i:EventTrigger> 
        <local:ScrollTrigger> 
         <ei:ChangePropertyAction TargetObject="{Binding ElementName=popup}" PropertyName="IsOpen" Value="False"/> 
        </local:ScrollTrigger> 
       </i:Interaction.Triggers> 
      </Button> 
      <Popup Name="popup" PlacementTarget="{Binding ElementName=button}"> 
       <TextBlock Background="White" Text="Sample text"/> 
      </Popup> 
      <Rectangle Width="100" Height="100" Fill="Red"/> 
      <Rectangle Width="100" Height="100" Fill="Green"/> 
      <Rectangle Width="100" Height="100" Fill="Blue"/> 
      <Rectangle Width="100" Height="100" Fill="Yellow"/> 
     </StackPanel> 
    </ScrollViewer> 
</Grid> 

Abbiamo un pulsante che apre un Popup e qualsiasi scrolling in qualsiasi genitore ScrollViewer provoca le ScrollTrigger azioni da fuoco e poi siamo in grado di chiudere il popup. Si noti che il trigger è collegato allo Button e non allo Popup. Possiamo usare qualsiasi elemento vicino che si trova nell'albero visivo. Si noti inoltre che utilizziamo un altro trigger per aprire Popup ma il modo in cui si apre non è importante per la domanda originale.

Ecco la ScrollTrigger:

class ScrollTrigger : TriggerBase<FrameworkElement> 
{ 
    protected override void OnAttached() 
    { 
     AssociatedObject.Loaded += new RoutedEventHandler(AssociatedObject_Loaded); 
    } 

    void AssociatedObject_Loaded(object sender, RoutedEventArgs e) 
    { 
     foreach (var scrollViewer in GetScrollViewers()) 
      scrollViewer.ScrollChanged += new ScrollChangedEventHandler(scrollViewer_ScrollChanged); 
    } 

    void scrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e) 
    { 
     InvokeActions(e.OriginalSource); 
    } 

    IEnumerable<ScrollViewer> GetScrollViewers() 
    { 
     for (DependencyObject element = AssociatedObject; element != null; element = VisualTreeHelper.GetParent(element)) 
      if (element is ScrollViewer) yield return element as ScrollViewer; 
    } 
} 

Il ScrollTrigger è molto semplice, solo che attribuisce a tutti i genitori ScrollChanged eventi e spara qualsiasi azioni contenute. Nell'esempio utilizziamo lo ChangePropertyAction per chiudere lo Popup.

Se non si ha familiarità con i comportamenti, installare l'Expression Blend 4 SDK e aggiungere questi spazi dei nomi:

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" 

e aggiungere System.Windows.Interactivity e Microsoft.Expression.Interactions al progetto.

1

Non riesco a immaginare come sono i vostri controlli, ma non potete basare la vostra apertura/chiusura di un controllo sull'evento Focus? E se perde lo stato attivo, per chiudere il popup? Forse capisco male, puoi pubblicare uno snippet di codice? Daniel

Problemi correlati