【问题标题】:Silverlight 3 - ListBox : how to achieve Smooth Scroll and catch MouseDown/MouseUp eventsSilverlight 3 - ListBox:如何实现平滑滚动和捕捉 MouseDown/MouseUp 事件
【发布时间】:2010-11-24 04:36:59
【问题描述】:

我正在尝试根据我的需要调整 ListBox 的行为,但遇到了几个问题

1) 如何以编程方式设置 ListBox 的滚动位置
ListBox 不提供对其内部 ScrollViewer 的访问器,因此您无法将其滚动到您想要的任何位置。

2) 如何准确设置垂直滚动(即如何平滑滚动)?
默认情况下,无法通过一次滚动一个完整元素来滚动列表(Listbox 将始终确保第一个元素完全显示)

这种行为在大多数情况下是可以的,但不是我的:我想要一个平稳的运动......),

WPF 可以解决这个问题,但 Silverlight 没有(请参阅问题 "is-it-possible-to-implement-smooth-scroll-in-a-wpf-listview")。

3) 如何捕捉 MouseDown 和 MouseUp 事件:
如果您将 ListBox 子类化,您可能能够捕获 MouseUp 和 MouseMove 事件。但是 MouseUp 事件永远不会被触发(我怀疑它被 ListBox 子元素吃掉了)

【问题讨论】:

    标签: silverlight listbox smooth-scrolling


    【解决方案1】:

    我已经找到了答案,所以我会自己回答。


    1) 如何使 ListBox 平滑滚动:
    此问题在 SilverLight 2 中没有发生,它仅在 SilverLight 3 中发生,其中引入了 VirtualizedStackPanel。
    VirtualizedStackPanel 在大列表的情况下可以更快地刷新(因为只绘制可见元素)

    有一个解决方法(注意,它不应该用于大型列表):您重新定义 ListBox 的 ItemPanelTemplate,以便它使用 StackPanel:

    <navigation:Page.Resources>
        <ItemsPanelTemplate x:Key="ItemsPanelTemplate">
            <StackPanel/>
        </ItemsPanelTemplate>
    </navigation:Page.Resources>
    
    <StackPanel Orientation="Vertical"  x:Name="LayoutRoot">                       
            <ListBox x:Name="list" ItemsPanel="{StaticResource ItemsPanelTemplate}">
            </ListBox>
    </StackPanel>
    

    2) 如何以编程方式更改滚动位置
    请参阅下面的 ListBox 的子类:它提供了 ListBox 内部 ScrollViewer 的访问器


    3) 如何捕捉列表框中的 MouseDown / Move / Up 事件:

    创建一个 ListBox 的子类,如下所示。三种方法:

     internal void MyOnMouseLeftButtonDown(MouseButtonEventArgs e)  
     protected override void OnMouseMove(MouseEventArgs e)  
     protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)  
    

    将被调用,您可以对它们做任何您想做的事情。有一个微妙的技巧是永远不会调用 ListBox 的 OnMouseLeftButtonDown 方法:您需要实现 ListBoxItem 的子类,您可以在其中处理此事件。

    using System;
    using System.Collections.Generic;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Ink;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    
    namespace MyControls
    {
      //In order for this class to be usable as a control, you need to create a folder
      //named "generic" in your project, and a "generic.xaml" file in this folder
      //(this is where you can edit the default look of your controls)
      //
      /*
       * Typical content of an "empty" generic.xaml file : 
        <ResourceDictionary
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:VideoControls">
        </ResourceDictionary>
       */
      public class MyListBox : ListBox
      {
        public MyListBox()
        {
            DefaultStyleKey = typeof(ListBox);
        }
    
        public override void OnApplyTemplate()
        {
          base.OnApplyTemplate();
        }
    
        #region ScrollViewer / unlocking access related code
        private ScrollViewer _scrollHost;
        public ScrollViewer ScrollViewer
        {
          get 
          {
            if (_scrollHost == null)
              _scrollHost = FindVisualChildOfType<ScrollViewer>(this);
            return _scrollHost; 
          }
        }
    
        public static childItemType FindVisualChildOfType<childItemType>(DependencyObject obj)
          where childItemType : DependencyObject
        {
          // Search immediate children first (breadth-first)
          for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
          {
            DependencyObject child = VisualTreeHelper.GetChild(obj, i);
    
            if (child != null && child is childItemType)
              return (childItemType)child;
    
            else
            {
              childItemType childOfChild = FindVisualChildOfType<childItemType>(child);
    
              if (childOfChild != null)
                return childOfChild;
            }
          }
    
          return null;
        }
        #endregion
    
        //Modify MyListBox so that it uses MyListBoxItem instead of ListBoxItem
        protected override DependencyObject GetContainerForItemOverride()
        {
          MyListBoxItem item = new MyListBoxItem(this);
          if (base.ItemContainerStyle != null)
          {
            item.Style = base.ItemContainerStyle;
          }
    
          return item;
        }
    
        //OnMouseLeftButtonUp is never reached, since it is eaten by the Items in the list...
        /*
        protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
        {
          base.OnMouseLeftButtonDown(e);
          e.Handled = false;
        }
        */
    
        internal void MyOnMouseLeftButtonDown(MouseButtonEventArgs e)
        {
        }
    
        protected override void OnMouseMove(MouseEventArgs e)
        {
          base.OnMouseMove(e);
        }
    
        protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
        {
          base.OnMouseLeftButtonUp(e);
        }
    
    
      }
    
    
    
    
    
    
      public class MyListBoxItem : ListBoxItem
      {
        MyListBox _customListBoxContainer;
    
        public MyListBoxItem()
        { }
    
        public MyListBoxItem(MyListBox customListBox)
        {
          this._customListBoxContainer = customListBox;
        }
    
        protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
        {
          base.OnMouseLeftButtonDown(e);
    
          if (this._customListBoxContainer != null)
          {
            this._customListBoxContainer.MyOnMouseLeftButtonDown(e);
          }
    
        }
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-13
      • 1970-01-01
      • 1970-01-01
      • 2014-06-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多