2017-03-01 85 views
1

我在wpf usercontrol中有幾個擴展器控件。 當我展開擴展器時,如果可能,我想自動滾動以便整個擴展器可見。或者至少是這樣,新擴展的擴展器儘可能地「上升」。我如何滾動,以便在擴展擴展器後可見控件

當我現在做它在底部一個它擴展窗口邊緣下,我不能看到擴展器中的控件,而無需手動滾動到他們。

我想從XAML做到這一點,而不是代碼隱藏。 這可能嗎? 我使用MVVM模式。

林假設我必須使用觸發器的擴展,但我不知道如何瓶坯BringToView功能

高層佈局:

<ScrollViewer> 
    <UserControl> 
    <Grid> 
     <Expander> 
     ... 
     </Expander> 
     <Expander> 
     ... 
     </Expander> 
     <Expander> 
     ... 
     </Expander> 
    </Grid> 
    </UserControl> 
</ScrollViewer> 

回答

3

手柄Expanded事件並調用BringIntoView()方法:

private void Expander_Expanded(object sender, RoutedEventArgs e) 
{ 
    ((Expander)sender).BringIntoView(); 
} 

請注意,你應該使用的StackPanel或別的東西,而不是Grid

<ScrollViewer Name="sv"> 
    <UserControl> 
     <StackPanel> 
      <Expander> 
       <Border Height="1000" Background="Red"/> 
      </Expander> 
      <Expander> 
       <Border Height="1000" Background="Blue"/> 
      </Expander> 
      <Expander Expanded="Expander_Expanded"> 
       <Border Height="1000" Background="Green"/> 
      </Expander> 
     </StackPanel> 
    </UserControl> 
</ScrollViewer> 

編輯

您可能需要使用此附加屬性:

public static class ExpanderEx 
{ 
    public static readonly DependencyProperty BringIntoViewOnExpandProperty = 
          DependencyProperty.RegisterAttached("BringIntoViewOnExpand", 
           typeof(bool), typeof(ExpanderEx), 
           new PropertyMetadata(false, OnBringIntoViewOnExpandChanged)); 


    public static bool GetBringIntoViewOnExpand(DependencyObject obj) 
    { 
     return (bool)obj.GetValue(BringIntoViewOnExpandProperty); 
    } 
    public static void SetBringIntoViewOnExpand(DependencyObject obj, bool value) 
    { 
     obj.SetValue(BringIntoViewOnExpandProperty, value); 
    } 
    private static void OnBringIntoViewOnExpandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     if (d is Expander) 
     { 
      Expander obj = (Expander)d; 
      if (e.NewValue.Equals(true)) 
       obj.Expanded += Obj_Expanded; 
      else 
       obj.Expanded -= Obj_Expanded; 
     } 
    } 

    private static void Obj_Expanded(object sender, RoutedEventArgs e) 
    { 
     ((Expander)sender).BringIntoView(); 
    } 
} 

,並在XAML:

<ScrollViewer Name="sv"> 
    <UserControl> 
     <StackPanel> 
      <Expander local:ExpanderEx.BringIntoViewOnExpand="True"> 
       <Border Height="1000" Background="Red"/> 
      </Expander> 
      <Expander local:ExpanderEx.BringIntoViewOnExpand="True"> 
       <Border Height="1000" Background="Blue"/> 
      </Expander> 
      <Expander local:ExpanderEx.BringIntoViewOnExpand="True"> 
       <Border Height="1000" Background="Green"/> 
      </Expander> 
     </StackPanel> 
    </UserControl> 
</ScrollViewer> 
+0

我想這一點,和它的工作。但不是以某種方式讓它工作:)我對wpf的新手如此忍受着我。我在哪裏放置ExpanderEx類,以便我可以在許多視圖中重複使用它?當我嘗試它,我不得不把這個類放在與視圖相同的項目中,並在視圖代碼隱藏的內部...那個不能正確的... – merger

+0

選擇你的偏好。它是一個單獨的靜態類。例如,創建一個** extentions.cs **文件並將您的擴展放在那裏。重要的是要正確設置[XAML名稱空間聲明](https://msdn.microsoft.com/en-us/library/ms747086(v = vs.110).aspx)。 – Ron

+0

我在一個靜態類中。當我測試之前,我猜測我做錯了什麼。現在我把這個類移到了一個共享項目中,讓VS在xaml文件中創建名稱空間引用,重新編譯,並且它工作正常!謝謝,你的評論讓我以另一種方式嘗試同樣的事情,並得到它的工作:) – merger

2

給每個Expander此處理其Expanded事件。看起來您正在定義UserControl內的擴展器,因此遇到ScrollViewer是個問題。一種選擇是給你的UserControl一個ScrollViewer依賴屬性,所有者將綁定到任何ScrollViewer包含它。我不喜歡那樣。相反,我寫了一個幫助函數,查找可視化樹,並找到最近的父項ScrollViewer(如果有的話)。

private void Expander_Expanded(object sender, RoutedEventArgs e) 
{ 
    var scrollViewer = GetNearestScrollViewerParent(); 

    if (scrollViewer == null) 
     return; 

    var expander = (Expander)sender; 

    UIElement container = VisualTreeHelper.GetParent(expander) as UIElement; 
    Point relativeLocation = expander.TranslatePoint(new Point(0, 0), container); 

    scrollViewer.ScrollToVerticalOffset(relativeLocation.Y); 
} 

public ScrollViewer GetNearestScrollViewerParent() 
{ 
    for (var parent = VisualTreeHelper.GetParent(this); 
     parent != null; 
     parent = VisualTreeHelper.GetParent(parent)) 
    { 
     if (parent is ScrollViewer) 
      return parent as ScrollViewer; 
    } 

    return null; 
} 

XAML:

<UserControl.Resources> 
    <Style TargetType="Expander" BasedOn="{StaticResource {x:Type Expander}}"> 
     <EventSetter Event="Expanded" Handler="Expander_Expanded" /> 
    </Style> 
</UserControl.Resources>