0
ScrollViewer
不滾動到頂部。任何線索?ScrollViewer不滾動到頂部
用戶控件
public class AniScrollViewer : ScrollViewer
{
//Register a DependencyProperty which has a onChange callback
public static DependencyProperty CurrentVerticalOffsetProperty = DependencyProperty.Register("CurrentVerticalOffset", typeof(double), typeof(AniScrollViewer), new PropertyMetadata(new PropertyChangedCallback(OnVerticalChanged)));
public static DependencyProperty CurrentHorizontalOffsetProperty = DependencyProperty.Register("CurrentHorizontalOffsetOffset", typeof(double), typeof(AniScrollViewer), new PropertyMetadata(new PropertyChangedCallback(OnHorizontalChanged)));
//When the DependencyProperty is changed change the vertical offset, thus 'animating' the scrollViewer
private static void OnVerticalChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
AniScrollViewer viewer = d as AniScrollViewer;
viewer.ScrollToVerticalOffset((double)e.NewValue);
}
//When the DependencyProperty is changed change the vertical offset, thus 'animating' the scrollViewer
private static void OnHorizontalChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
AniScrollViewer viewer = d as AniScrollViewer;
viewer.ScrollToHorizontalOffset((double)e.NewValue);
}
public double CurrentHorizontalOffset
{
get { return (double)this.GetValue(CurrentHorizontalOffsetProperty); }
set { this.SetValue(CurrentHorizontalOffsetProperty, value); }
}
public double CurrentVerticalOffset
{
get { return (double)this.GetValue(CurrentVerticalOffsetProperty); }
set { this.SetValue(CurrentVerticalOffsetProperty, value); }
}
}
主代碼
public partial class Window1 : Window
{
Random rnd = new Random();
private const int _ITEM_COUNT = 20;
Point relativePoint;
Storyboard sb = new Storyboard();
Button btn;
public Window1()
{
InitializeComponent();
sb.Completed += (o, s) => ScrollItems();
//Create some buttons ;)
for (int i = 0; i < _ITEM_COUNT; i++)
{
Button btn = CreateButton(i);
ListViewItem item = new ListViewItem();
item.Tag = btn;
item.Content = "Button " + i.ToString();
cbJumpTo.Items.Add(item);
mainContent.Children.Add(btn);
}
labelH.Content = mainViewer.Height;
}
/// <summary>
/// Create a new button... There are some properties that need to be set, since this is a
/// SIMPLE demo, this should be fine.
/// </summary>
/// <param name="index">index of the button</param>
/// <returns>Created button</returns>
private Button CreateButton(int index)
{
Button btn = new Button();
btn.Content = "Button " + index.ToString();
int h = rnd.Next(30, 500);
btn.Height = h;
btn.Margin = new Thickness(5);
return btn;
}
/// <summary>
/// Animate the scrollviewer the the selected item from the combobox
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnAnimate_Click(object sender, RoutedEventArgs e)
{
//Get the position of the button located in the tag
btn = ((ListViewItem)cbJumpTo.SelectedItem).Tag as Button;
relativePoint = btn.TransformToAncestor(mainContent).Transform(new Point(0, 0));
ScrollToPosition(relativePoint.X, relativePoint.Y);
}
/// <summary>
/// Create a new animation to the x,y offset. I beleive you need the have .NET 3.5 SP1 installed for
/// this to work. If you don't you can't call Storyboard.SetTarget.
/// </summary>
/// <param name="x">X position</param>
/// <param name="y">Y position</param>
private void ScrollToPosition(double x, double y)
{
DoubleAnimation vertAnim = new DoubleAnimation();
vertAnim.From = mainViewer.VerticalOffset;
vertAnim.To = y;
vertAnim.DecelerationRatio = .2;
vertAnim.Duration = new Duration(TimeSpan.FromMilliseconds(25000));
DoubleAnimation horzAnim = new DoubleAnimation();
horzAnim.From = mainViewer.HorizontalOffset;
horzAnim.To = x;
horzAnim.DecelerationRatio = .2;
horzAnim.Duration = new Duration(TimeSpan.FromMilliseconds(1000));
sb.Children.Add(vertAnim);
sb.Children.Add(horzAnim);
Storyboard.SetTarget(vertAnim, mainViewer);
Storyboard.SetTargetProperty(vertAnim, new PropertyPath(AniScrollViewer.CurrentVerticalOffsetProperty));
Storyboard.SetTarget(horzAnim, mainViewer);
Storyboard.SetTargetProperty(horzAnim, new PropertyPath(AniScrollViewer.CurrentHorizontalOffsetProperty));
sb.Begin(this);
}
private void ScrollItems()
{
mainViewer.ScrollToTop(); // It does not scroll to top
}
}
XAML
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="50"></RowDefinition>
</Grid.RowDefinitions>
<local:AniScrollViewer x:Name="mainViewer" Grid.Row="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<StackPanel x:Name="mainContent"></StackPanel>
</local:AniScrollViewer>
<StackPanel Margin="10,10,0,10" Grid.Row="1" Orientation="Horizontal" Width="258">
<ComboBox x:Name="cbJumpTo" Margin="5" Width="84.884"></ComboBox>
<Button x:Name="btnAnimate" Margin="5" Click="btnAnimate_Click">Start Animation</Button>
<Label x:Name="labelH" Content="Label"/>
</StackPanel>
</Grid>