一.预期实现效果
二.代码
xaml代码
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="20"/>
</Grid.ColumnDefinitions>
<RepeatButton Click="Button_Click_1" Style="{StaticResource Style_Button_ImageAreaRPButton}" Width="20" Height="36">
<Image Source="{StaticResource left}" Margin="5"/>
</RepeatButton>
<scr:SmoothScrollViewer x:Name="sc1" Grid.Column="1" ScrollViewer.HorizontalScrollBarVisibility="Hidden"
ScrollViewer.VerticalScrollBarVisibility="Hidden" ScrollChanged="sc1_ScrollChanged" Margin="-10 0">
<ItemsControl ItemsSource="{Binding ElementName=ItemSlidCtrl, Path=ItemsResource, UpdateSourceTrigger=PropertyChanged}"
Style="{Binding ElementName=ItemSlidCtrl, Path=ItemsStyle, UpdateSourceTrigger=PropertyChanged}">
</ItemsControl>
</scr:SmoothScrollViewer>
<RepeatButton Grid.Column="2" Click="Button_Click" Style="{StaticResource Style_Button_ImageAreaRPButton}" Width="20" Height="36">
<Image Source="{StaticResource right}" Margin="5"/> //换成自己按钮的资源
</RepeatButton>
</Grid>
xaml.cs代码
double m_ScrollStepRatio = 0.0; //滚动条的归一化步进长度
double m_ScrollPositionRatio = 0.0; //滚动条的归一化位置
bool flag;
public ItemSlidUserCtrl()
{
InitializeComponent();
}
public object ItemsResource
{
get { return (object)GetValue(ItemsResourceProperty); }
set { SetValue(ItemsResourceProperty, value); }
}
//注册ItemsResource依赖属性
public static readonly DependencyProperty ItemsResourceProperty =
DependencyProperty.Register("ItemsResource", typeof(object), typeof(ItemSlidUserCtrl), new PropertyMetadata(null));
public Style ItemsStyle
{
get { return (Style)GetValue(ItemsStyleProperty); }
set { SetValue(ItemsStyleProperty, value); }
}
//注册VerticalScrollRatio依赖属性
public static readonly DependencyProperty ItemsStyleProperty =
DependencyProperty.Register("ItemsStyle", typeof(Style), typeof(ItemSlidUserCtrl), new PropertyMetadata(null));
private void Button_Click_1(object sender, RoutedEventArgs e)
{
sc1.LineLeft();//向右滚动
m_ScrollPositionRatio = sc1.ContentHorizontalOffset / sc1.ScrollableWidth;
flag = true;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
sc1.LineRight();//向右滚动
m_ScrollPositionRatio = sc1.ContentHorizontalOffset / sc1.ScrollableWidth;
flag = true;
}
private void sc1_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
try
{
if (flag)
{
m_ScrollStepRatio = sc1.ViewportWidth / (sc1.ExtentWidth - sc1.ViewportWidth);
if (e.HorizontalChange < 0)
sc1.SmoothScroll(m_ScrollStepRatio, m_ScrollPositionRatio, ScrollDirection.Left);
else if (e.HorizontalChange > 0)
sc1.SmoothScroll(m_ScrollStepRatio, m_ScrollPositionRatio, ScrollDirection.Right);
flag = false;
}
}
catch(Exception ex)
{
LogOutput.WriteErrorLog("sc1_ScrollChanged error : " + ex.Message);
}
}
flag是控制判断每次滚动一次的标志,去除的话则是一滚到底。
辅助类
public class SmoothScrollViewer : ScrollViewer
{
/// <summary>
/// 垂直归一化步进长度
/// </summary>
public double VerticalScrollRatio
{
get { return (double)GetValue(VerticalScrollRatioProperty); }
set { SetValue(VerticalScrollRatioProperty, value); }
}
//注册VerticalScrollRatio依赖属性
public static readonly DependencyProperty VerticalScrollRatioProperty =
DependencyProperty.Register("VerticalScrollRatio", typeof(double), typeof(SmoothScrollViewer), new PropertyMetadata(0.0, new PropertyChangedCallback(V_ScrollRatioChangedCallBack)));
private static void V_ScrollRatioChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var scrollViewer = (ScrollViewer)(d);
if (scrollViewer != null)
{
scrollViewer.ScrollToVerticalOffset((double)(e.NewValue) * scrollViewer.ScrollableHeight);
}
}
/// <summary>
/// 水平归一化步进长度
/// </summary>
public double HorizontalScrollRatio
{
get { return (double)GetValue(HorizontalScrollRatioProperty); }
set { SetValue(HorizontalScrollRatioProperty, value); }
}
//注册HorizontalScrollRatio依赖属性
public static readonly DependencyProperty HorizontalScrollRatioProperty =
DependencyProperty.Register("HorizontalScrollRatio", typeof(double), typeof(SmoothScrollViewer), new PropertyMetadata(0.0, new PropertyChangedCallback(H_ScrollRatioChangedCallBack)));
private static void H_ScrollRatioChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var scrollViewer = (ScrollViewer)(d);
if (scrollViewer != null)
{
scrollViewer.ScrollToHorizontalOffset((double)(e.NewValue) * scrollViewer.ScrollableWidth);
}
}
}
具体使用
<users:ItemSlidUserCtrl x:Name="popularList" Grid.Row="1" Background="Transparent" ItemsResource="{Binding PopularAppList}" ItemsStyle="{StaticResource Style_APP_PolpularList}" </users:ItemSlidUserCtrl>
这边把ItemSource换成自己的集合,style换成内部的空间
说明
本文章提供的是一个较为通用的滚动外包控件,可以理解为ScrollView的灵活变换