我在wpf usercontrol中有几个Expander控件。 当我扩展扩展器时,我想自动滚动,以便在可能的情况下可以看到整个扩展器。或至少所以新扩展的扩展器尽可能“向上”。
当我现在在底部时,它会在窗口边缘下方展开,我无法在扩展器中看到控件而无需手动滚动它们。
我想从XAML而不是代码隐藏中做到这一点。 有可能吗? 我正在使用MVVM模式。
我假设我必须在扩展器上使用触发器,但我不知道如何预先形成BringToView功能
高级布局:
grep
答案 0 :(得分: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>
答案 1 :(得分: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>