我會告訴你我做了什麼,也許你會發現它足夠。我想要一個全屏圖像查看器,可以讓我滑動到下一個(或之前)的圖像,但讓它捕捉到圖像而不是正常的滾動。
我使用了禁用內部scrollViewer的全屏列表框(請參閱XAML),然後使用一些附加的依賴項屬性來獲取內部scrollViewer的水平(和垂直)偏移的屬性(這樣我就可以爲自己的滾動設置動畫效果) 。我的實現涉及更多,因爲我想要縮放(然後平移)圖像,但是轉到下一個圖像的部分並不難。
聲明:我從StackOverflow和其他網站的幾個來源獲取代碼。我不記得我是從哪裏得到它們的,但是我沒有自己想出這些想法。如果我知道該把它放在哪裏,我很樂意給予獎勵。
首先,創建一個名爲ScrollViewerEx新類:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
namespace ImageViewer
{
public class ScrollViewerEx
{
public static double GetHOffset(ScrollViewer obj)
{
return (double)obj.GetValue(ScrollViewer.HorizontalOffsetProperty);
}
public static void SetHOffset(ScrollViewer obj, double value)
{
obj.SetValue(HOffsetProperty, value);
}
// Using a DependencyProperty as the backing store for HOffset. This enables animation, styling, binding, etc...
public static readonly DependencyProperty HOffsetProperty =
DependencyProperty.RegisterAttached("HOffset", typeof(double), typeof(ScrollViewerEx), new PropertyMetadata(new PropertyChangedCallback(OnHOffsetChanged)));
private static void OnHOffsetChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
var scroll = sender as ScrollViewer;
scroll.ScrollToHorizontalOffset((double)e.NewValue);
}
public static double GetVOffset(ScrollViewer obj)
{
return (double)obj.GetValue(ScrollViewer.VerticalOffsetProperty);
}
public static void SetVOffset(ScrollViewer obj, double value)
{
obj.SetValue(VOffsetProperty, value);
}
// Using a DependencyProperty as the backing store for VOffset. This enables animation, styling, binding, etc...
public static readonly DependencyProperty VOffsetProperty =
DependencyProperty.RegisterAttached("VOffset", typeof(double), typeof(ScrollViewerEx), new PropertyMetadata(new PropertyChangedCallback(OnVOffsetChanged)));
private static void OnVOffsetChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
var scroll = sender as ScrollViewer;
scroll.ScrollToVerticalOffset((double)e.NewValue);
}
}
}
好吧,讓我們假設你有一個像下面的一種製備的列表框。我的例子中的Images屬性是一個名爲PictureModel的類,裏面有一個ImageSource。我沒有顯示我的ItemTemplate,只是放入一個Image並將Source綁定到ImageSource。注意列表框下方的矩形。我把所有的觸摸代碼放在那裏,因爲當我使用縮放圖像時,我的座標系正在改變。使用矩形覆蓋使其具有所有觸摸的標準屏幕座標。你可能不需要這個。
<ListBox ItemsSource="{Binding Images}"
x:Name="listBox"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Disabled"
ScrollViewer.ManipulationMode="Control"
Loaded="listBox_Loaded_1"
>
<ListBox.Resources>
<Storyboard x:Name="ScrollStoryboard">
<DoubleAnimation x:Name="AnimationH" Duration="0:0:0.5">
<DoubleAnimation.EasingFunction>
<CubicEase EasingMode="EaseInOut"/>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
<DoubleAnimation x:Name="AnimationV" Duration="0:0:0.5">
<DoubleAnimation.EasingFunction>
<CubicEase EasingMode="EaseInOut"/>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</ListBox.Resources>
<ListBox.ItemContainerStyle>
<StaticResource ResourceKey="ListBoxItemPivotStyle"/>
</ListBox.ItemContainerStyle>
</ListBox>
<Rectangle Fill="Transparent"
x:Name="TouchRectangle"
ManipulationCompleted="Rectangle_ManipulationCompleted_1"
ManipulationDelta="Rectangle_ManipulationDelta_1"
ManipulationStarted="Rectangle_ManipulationStarted_1"/>
好吧,另一個關鍵部分。確保你把這個放在頁面的構造函數中。這是允許您爲您的滾動查看器偏移更改設置動畫效果的。
Storyboard.SetTargetProperty(ScrollStoryboard.Children[0], new PropertyPath(ScrollViewerEx.HOffsetProperty));
Storyboard.SetTargetProperty(ScrollStoryboard.Children[1], new PropertyPath(ScrollViewerEx.VOffsetProperty));
得到永久的參考列表框內部的ScrollViewer:
private void listBox_Loaded_1(object sender, RoutedEventArgs e)
{
scrollviewer = GetVisualChild<ScrollViewer>(listBox);
}
最後,處理操縱事件。使列表框滾動動畫的關鍵之一是操作完成事件。我沒有使用垂直偏移,只是水平偏移。變量vm.Position是沿scrollviewer.horizontaloffset的計算位置。基本上,如果你在第5張圖片上,然後將屏幕寬度乘以4得到水平偏移量。
private void Rectangle_ManipulationCompleted_1(object sender, ManipulationCompletedEventArgs e)
{
if (e.FinalVelocities.LinearVelocity.X > 2000)
{
if (ScrollStoryboard.GetCurrentState() != ClockState.Stopped)
ScrollStoryboard.Stop(); // ensure storyboard stopped after previous run
AnimationH.SetValue(DoubleAnimation.FromProperty, scrollviewer.HorizontalOffset);
AnimationH.SetValue(DoubleAnimation.ToProperty, (double)vm.Position);
Storyboard.SetTarget(ScrollStoryboard, scrollviewer);
ScrollStoryboard.Begin();
}
}
我希望這會有所幫助。就像我說的,除了從ListBox獲得的內置UI虛擬化之外,我所做的完整實現還包括數據虛擬化。那和縮放。它不完全準備好發佈,但這會讓你開始。
@all,如果你決定downvote,請考慮後解釋! – user2490629
這是因爲,雖然你解釋了你的問題,但是你沒有顯示任何不符合預期的代碼,或者你沒有做任何編碼工作。 –
感謝@TI,但有時沒有代碼,也不知道如何執行它..我可以添加一個愚蠢的全景圖代碼,並說我看不到頂部空間,但有什麼好處? – user2490629