Silverlight 3 - ListBox: wie glatt Scroll und fangen MouseDown- / MouseUp Ereignisse zu erreichen

StackOverflow https://stackoverflow.com/questions/1354708

Frage

Ich versuche, das Verhalten der List-Box für meine Bedürfnisse anzupassen, und ich lief in einige Probleme

1) Wie kann man programmatisch die Scroll-Position des ListBox
eingestellt Die List-Box keine Accessor seines inneren Scroll, so dass Sie nicht bewegen können, wo immer Sie wollen.

2) Wie genau die vertikalen Scrollen gesetzt (das heißt, wie eine glatten Scrollen haben)?
Standardmäßig gibt es keine Möglichkeit, die Liste andere durch Scrollen ein komplettes Element zu einem Zeitpunkt, zu blättern (die Listbox wird immer darauf achten, dass das erste Element ist vollständig dargestellt)

Dieses Verhalten ist in Ordnung, in den meisten Fällen, aber nicht von mir: Ich möchte eine glatte Bewegung ...)

Es gibt eine Lösung für dieses Problem mit WPF, aber nicht mit Silverlight (siehe Frage " is-it-möglich implementierende-glatt-Scroll-in-a-wpf-Listenansicht ").

3) Wie die MouseDown- und MouseUp Ereignisse fangen:
Wenn Sie die List-Box Unterklasse, könnten Sie in der Lage sein, die MouseUp und Mouse Ereignisse zu fangen. Allerdings wird das Ereignis MouseUp nie gefeuert (ich vermute, dass es durch die ListBox Subelemente gegessen wird)

War es hilfreich?

Lösung

Ich habe die Antwort gefunden, so dass ich mich beantworten.


1) Wie die ListBox Scroll glatt zu machen:
Dieses Problem trat nicht in Silverlight 2, und es geschieht nur mit Silverlight 3, bei dem der VirtualizedStackPanel eingeführt wurde.
Die VirtualizedStackPanel ermöglicht viel schneller aktualisiert im Fall von großen Listen (als nur die sichtbaren Elemente werden gezogen)

Es gibt eine Abhilfe für dieses (Vorsicht, sollte es nicht auf riesige Listen verwendet werden): Sie können die ItemPanelTemplate der List-Box neu zu definieren, so dass es verwendet 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) Wie programmatisch die Scroll-Position
ändern Siehe die Unterklasse von List-Box unten: es einen Accessor zum internen Scroll der List-Box bietet


3) Wie die MouseDown- / Move / Up Ereignisse im Listenfeld fangen:

Erstellen Sie eine Unterklasse von ListBox wie unten gezeigt. Die drei Methoden:

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

wird aufgerufen und Sie können tun, was Sie mit ihnen wollen. Es ist ein subtiler Trick, der ist, dass die OnMouseLeftButtonDown Methode der List-Box nie aufgerufen wird. Sie brauchen eine Unterklasse von ListBoxItem zu implementieren, wo man dieses Ereignis verarbeiten kann

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

    }
  }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top