matlab两个listbox的滚动条,如何用两种方式同时实现ListBox的滚动功能

今天,要用WPF实现一个可以通过Windows触屏左右滑动的ListBox控件,并且,同时也可以通过点击两个按钮,进行左右滑动。

实现这个控件,有几个难点:

两种方式,都需要有一个共同的值或方式来记录滑动的距离和方向。否则通过一种方式滑动以后,再用另外一种方式,就会出现错误的距离滑动。

滑动的距离不容易获取,因为ListBox没有类似于OffSet的属性。

当ListBox的内容的元素比较多的时候,也就是可以滑动的时候,不容易得知那些元素是露在外面的。

Xaml的相关代码:

x:Name="navItemsListBox"

ScrollViewer.VerticalScrollBarVisibility="Disabled"

ScrollViewer.HorizontalScrollBarVisibility="Hidden"

ScrollViewer.CanContentScroll="False"

ScrollViewer.IsDeferredScrollingEnabled="True"

VirtualizingStackPanel.IsVirtualizing="True"

VirtualizingPanel.ScrollUnit="Item"

Background="Transparent"

BorderThickness="0"

Width="840">

Width="70"

Height="35"/>

有种方法,可以实现第二种方式滚动:

navItemsListBox.ScrollIntoView(navItemsListBox.Items[++CurrentRightIndex]);

这种方法,可以让ListBox滚动到其包含的某个元素。但是因为不能记录滚动的具体位置,所以对第一种划屏的方式无能为力,所以这种方法不能采用。

有种方法,可以完美实现。

首先通过VisualTree的方法获得内嵌在ListBox中的ScrollViewer:

Decorator border = VisualTreeHelper.GetChild(navItemsListBox, 0) as Decorator;

if (border != null)

{

scrollViewer = border.Child as ScrollViewer;

if (scrollViewer != null)

{

scrollViewer.ScrollToHorizontalOffset(theOffset);

}

}

因为ScrollViewer是可以记录滚动的偏差的,比如HorizontalOffset属性就是记录水平的滚动偏差的。获取了内嵌在ListBox中的ScrollViewer,也就间接的获取了ListBox的滚动偏差。

然后,获取navItemsListBox中的ListBoxItem,用来计算每个元素的宽度和ListBox左右能滑动的最大宽度:

ListBoxItem theItem = (ListBoxItem)(navItemsListBox.ItemContainerGenerator.ContainerFromIndex(0));

var itemWidth = theItem.ActualWidth;

var itemsTotalWidth = (navItemsListBox.Items.Count - MAXSHOWNINDEX) * itemWidth;

其中,MAXSHOWNINDEX是ListBox能同时展现在外面的最多元素的个数。

那么这个方法的原理就是:因为无论是通过触屏滑屏还是点击按钮滚动,都会改变ListBox中ScrollViewer的HorizontalOffset的值(当然,也会触发ListBox的ScrollViewer.ScrollChanged事件,我就是通过这个事件来了解这个方法的),那么每次在点击按钮进行滚动的时候,首先要获取当前的HorizontalOffset的值,然后再用

scrollViewer.ScrollToHorizontalOffset(theOffset);

这个方法再次改变HorizontalOffset。这样,就通过HorizontalOffset这个值来统一管理两种滚动方法的偏移量了。

当然,以上功能可以直接采用ScrollViewer实现,但是由于历史代码遗留的原因,不得不采用ListBox。

最终的code-behind代码如下:

private const int MAXSHOWNINDEX = 9;

private ScrollViewer scrollViewer = new ScrollViewer();

private double theOffset = 0;

private void UserControl_Loaded(object sender, RoutedEventArgs e)

{

Decorator border = VisualTreeHelper.GetChild(navItemsListBox, 0) as Decorator;

if (border != null)

{

scrollViewer = border.Child as ScrollViewer;

if (scrollViewer != null)

{

scrollViewer.ScrollToHorizontalOffset(theOffset);

}

}

}

private void CategoryToRight(object sender, RoutedEventArgs e)

{

ListBoxItem theItem = (ListBoxItem)(navItemsListBox.ItemContainerGenerator.ContainerFromIndex(0));

var itemWidth = theItem.ActualWidth;

var itemsTotalWidth = (navItemsListBox.Items.Count - MAXSHOWNINDEX) * itemWidth;

theOffset = scrollViewer.HorizontalOffset;

if (theOffset + itemWidth > itemsTotalWidth)

{

theOffset = itemsTotalWidth;

}

else

theOffset += itemWidth;

scrollViewer.ScrollToHorizontalOffset(theOffset);

}

private void CategoryToLeft(object sender, RoutedEventArgs e)

{

ListBoxItem theItem = (ListBoxItem)(navItemsListBox.ItemContainerGenerator.ContainerFromIndex(0));

var itemWidth = theItem.ActualWidth;

theOffset = scrollViewer.HorizontalOffset;

if (theOffset - itemWidth < 0)

{

theOffset = 0;

}

else

theOffset -= itemWidth;

scrollViewer.ScrollToHorizontalOffset(theOffset);

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值