Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/cmake/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Silverlight 3-ListBox:如何实现平滑滚动并捕获MouseDown/MouseUp事件_Silverlight_Listbox_Smooth Scrolling - Fatal编程技术网

Silverlight 3-ListBox:如何实现平滑滚动并捕获MouseDown/MouseUp事件

Silverlight 3-ListBox:如何实现平滑滚动并捕获MouseDown/MouseUp事件,silverlight,listbox,smooth-scrolling,Silverlight,Listbox,Smooth Scrolling,我试图根据自己的需要调整列表框的行为,但遇到了几个问题 1) 如何通过编程设置列表框的滚动位置 ListBox不为其内部ScrollViewer提供访问器,因此您无法将其滚动到所需的任何位置 2) 如何准确设置垂直滚动(即如何平滑滚动)? 默认情况下,无法通过一次滚动一个完整的元素来滚动列表(列表框将始终确保第一个元素完全显示) 这种行为在大多数情况下是可以的,但不是我的:我想要一个平稳的动作 WPF可以解决此问题,但Silverlight不能(请参阅问题) 3) 如何捕获MouseDown和M

我试图根据自己的需要调整列表框的行为,但遇到了几个问题

1) 如何通过编程设置列表框的滚动位置
ListBox不为其内部ScrollViewer提供访问器,因此您无法将其滚动到所需的任何位置

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

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

WPF可以解决此问题,但Silverlight不能(请参阅问题)

3) 如何捕获MouseDown和MouseUp事件:

如果将ListBox子类化,则可能能够捕获MouseUp和MouseMove事件。但是MouseUp事件从未被触发(我怀疑它被ListBox子元素吃掉)

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


1) 如何使列表框平滑滚动:
此问题在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>
你可以用他们做任何你想做的事。有一个微妙的技巧,就是永远不会调用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);
      }

    }
  }
}
使用系统;
使用System.Collections.Generic;
Net系统;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Documents;
使用System.Windows.Ink;
使用System.Windows.Input;
使用System.Windows.Media;
使用System.Windows.Media.Animation;
使用System.Windows.Shapes;
命名空间MyControls
{
//为了使此类可用作控件,您需要创建一个文件夹
//在项目中命名为“generic”,并在此文件夹中创建一个“generic.xaml”文件
//(您可以在此处编辑控件的默认外观)
//
/*
*“空”generic.xaml文件的典型内容:
*/
公共类MyListBox:ListBox
{
公共MyListBox()
{
DefaultStyleKey=typeof(列表框);
}
应用程序模板()上的公共重写无效
{
base.OnApplyTemplate();
}
#区域滚动查看器/解锁访问相关代码
私有ScrollViewer\u scrollHost;
公共滚动查看器滚动查看器
{
得到
{
如果(_scrollHost==null)
_scrollHost=FindVisualChildOfType(此);
返回主机;
}
}
公共静态childItemType FindVisualChildOffType(DependencyObject obj)
其中childItemType:DependencyObject
{
//先搜索直系子女(广度优先)
for(int i=0;i
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);
      }

    }
  }
}