2010-02-22 3 views
8

WPF Popup을 열 때 (예 : ButtonClick) 상황을 상상해보십시오. 일부 항목이있는 PopupListBox이 직접 있으니 스크롤해야합니다. 이것이 Custom Control이고 ScrollViewer에 있다고 가정 해 보겠습니다.WPF가 스크롤링 부모 컨트롤을 감지 함

Popup 외부에서 마우스로 이동하고 스크롤하면 어떻게됩니까? 위 아래로 스크롤하지만 Popup이 열렸습니다! 그리고 그것이 문제입니다.

질문 : VisualTree의 다른 알 수없는 부모 컨트롤이 스크롤하기 시작했는지, 컨트롤 내부에서 어떻게 감지합니까? 이고 연속적으로 IsDropDownOpen = false으로 설정 되었습니까?

+0

동일한 질문과 문제가 있습니다. 내 그리드를 스크롤하고 사용자 지정 작업으로 내 팝업을 동일한 장소에 머물러있게하십시오! 나는 격자와 함께 팝업 스크롤해야합니다! – Evgeny

답변

10

ScrollViewer에 포함 된 요소와 함께 사용할 트리거를 작성할 수 있습니다.

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

우리는 PopupScrollTrigger 행동을 발사하고 우리가 팝업을 닫을 수 있습니다 원인 ScrollViewer 어떤 부모에있는 스크롤을 여는 버튼이 있습니다 : 여기에 완전한 샘플 응용 프로그램입니다. 트리거는 Popup이 아니라 Button에 연결됩니다. 우리는 비주얼 트리에있는 근처의 요소를 사용할 수 있습니다. Popup을 여는 데 또 다른 트리거를 사용하지만 원래 질문에는 중요하지 않습니다. 여기

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

ScrollTrigger은 매우 간단합니다, 그냥 모든 상위 ScrollChanged 이벤트에 부착하고이 작업을 포함 발생합니다. 이 샘플에서는 Popup을 닫기 위해 ChangePropertyAction을 사용합니다. 당신이 행동에 익숙하지 않은 경우

, 익스프레션 블렌드 4 SDK를 설치하고 다음의 네임 스페이스를 추가

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

및 프로젝트에 System.Windows.InteractivityMicrosoft.Expression.Interactions를 추가합니다.

1

컨트롤이 어떻게 보이지는 않지만 Focus 이벤트에서 컨트롤 열기/닫기를 기반으로 할 수는 없습니까? 그리고 초점을 잃으면 팝업을 닫으시겠습니까? 아마도 내가 잘못 이해하고 있습니다. 코드 스 니펫을 게시 할 수 있습니까? Daniel

관련 문제