2010-02-22 10 views
8

Stellen Sie sich die Situation vor, Sie öffnen ein WPF (z. B. durch ButtonClick). Sie haben eine ListBox direkt in der Popup mit einigen Elementen, so dass Sie scrollen können. Stellen Sie sich vor, das ist Ihr Custom Control und es befindet sich in der ScrollViewer.WPF erkennen scrollende übergeordnete Steuerung

Jetzt, wenn Sie mit der Maus aus der Popup Oberfläche bewegen und scrollen, was passiert? Sie scrollen rauf und runter aber mit Popup geöffnet! Und das ist das Problem.

Die Frage ist, wie aus dem Control zu erkennen ist, dass ein anderes unbekanntes Parent Control im VisualTree zu scrollen begonnen hat? und nacheinander setzen IsDropDownOpen = false?

+0

Ich habe die gleiche Frage und das Problem. Ich scrolle mein Raster und mein Popup mit benutzerdefinierten Operationen bleibt am selben Ort! Ich muss Popup mit Gitter scrollen! – Evgeny

Antwort

10

Wir können einen Trigger für die Verwendung mit Elementen innerhalb einer ScrollViewer schreiben. Dies ist die komplette Beispielanwendung:

<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> 

Wir haben eine Schaltfläche, die ein Popup und jedes Scrollen in allen Eltern öffnet ScrollViewer die ScrollTrigger Aktionen führen zu feuern und dann können wir das Popup schließen. Beachten Sie, dass der Trigger an die Button und nicht an die angeschlossen ist. Wir können jedes nahegelegene Element verwenden, das sich im visuellen Baum befindet. Beachten Sie auch, dass wir einen anderen Auslöser verwenden, um das Popup zu öffnen, aber wie es geöffnet wird, ist für die ursprüngliche Frage nicht wichtig. Hier

ist die 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; 
    } 
} 

Die ScrollTrigger ist sehr einfach, es hängt nur an alle Eltern ScrollChanged Ereignisse und feuert jede Aktionen enthalten. In der Probe verwenden wir die ChangePropertyAction, um die Popup zu schließen.

Wenn Sie nicht vertraut mit Verhaltensweisen sind, installieren Sie die Mischung 4 SDK Expression und fügen Sie diese Namensräume:

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

und fügen System.Windows.Interactivity und Microsoft.Expression.Interactions zu Ihrem Projekt.

1

Ich kann mir nicht vorstellen, wie Ihre Steuerelemente sind, aber können Sie das Öffnen/Schließen eines Steuerelements nicht auf das Focus-Ereignis anwenden? Und wenn es den Fokus verliert, um das Popup zu schließen? Vielleicht verstehe ich falsch, können Sie ein Code-Snippet posten? Daniel

Verwandte Themen