2017-03-01 6 views
1

wpf usercontrolに複数のExpanderコントロールがあります。 エキスパンダーをエキスパンドすると、可能であればエキスパンダー全体が表示されるように自動的にスクロールしたいと思います。または、atleastので、新しく拡張されたExpanderは可能な限り遠くにある。Expanderを展開した後にコントロールが表示されるようにスクロールするには

私は今、それをウィンドウの端の下に拡大し、手動でスクロールせずにエキスパンダーのコントロールを見ることができません。

そして、これはコードビハインドではなく、XAMLからやりたいと思っています。 それは可能ですか? MVVMパターンを使用しています。

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

をあなたの代わりにGridのStackPanelのか、何か他のものを使用する必要があることに注意してください:

<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

はそのExpandedイベントのために、各Expanderにこのハンドラを与える:私はパンダにトリガーを使用する必要がありますが、私はBringToView機能に

高位レイアウトをプリフォームする方法が分からないと仮定し

イム。 UserControlの中にエキスパンダーを定義しているようですので、ScrollViewerに行くことは問題です。あなたのUserControlScrollViewerが含まれているものにオーナーがバインドするように、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> 
関連する問題