Pergunta

Estou tentando adaptar o comportamento da caixa de listagem para minhas necessidades e encontrei vários problemas

1) Como você pode definir programaticamente a posição de rolagem da caixa de listagem
O ListBox não fornece um acessador ao seu scrollViewer interno para que você não possa rolá -lo para onde quiser.

2) Como definir com precisão a rolagem vertical (ou seja, como ter uma rolagem suave)?
Por padrão, não há como rolar a lista outra rolando um elemento completo por vez (a caixa de listagem sempre garantirá que o primeiro elemento seja mostrado inteiramente)

Esse comportamento é bom na maioria dos casos, mas não meu: eu quero um movimento suave ...),

Existe uma solução para esse problema com o WPF, mas não com Silverlight (veja a pergunta "Is-it-Possível para Implementar-Smooth-Scroll-in-A-WPF-ListView" ).

3) Como pegar os eventos de Mousedown e MouseUp:
Se você subclasse o ListBox, poderá pegar os eventos do MouseUp e Mousemove. No entanto, o evento MouseUp nunca é demitido (suspeito que esteja sendo comido pelos subelementos da caixa de listagem)

Foi útil?

Solução

Eu encontrei a resposta, então eu vou me responder.


1) Como fazer a caixa de listar rolar sem problemas:
Esse problema não aconteceu no Silverlight 2 e acontece apenas com o Silverlight 3, no qual o VirtualizedStackPanel foi introduzido.
O VirtualizedStackPanel permite uma atualização muito mais rápida no caso de listas enormes (como apenas os elementos visíveis são desenhados)

Há uma solução alternativa para isso (cuidado, não deve ser usado em listas enormes): você redefine o itemPaNETemplate do ListBox, para que ele use o 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) Como alterar programaticamente a posição de rolagem
Veja a subclasse da ListBox abaixo: fornece um acessador ao interno scrollViewer da caixa de listar


3) Como pegar os eventos de Mousedown / Mover / Up na ListBox:

Crie uma subclasse da ListBox, como mostrado abaixo. Os 3 métodos:

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

será chamado e você pode fazer o que quiser com eles. Há um truque sutil que é que o método OnMouseleftButtondown do ListBox nunca é chamado: você precisa implementar uma subclasse do ListBoxItem, onde pode lidar com este evento.

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);
      }

    }
  }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top