65.9K
CodeProject 正在变化。 阅读更多。
Home

WPF ListBox 的橡皮筋行为

starIconstarIconstarIconstarIconstarIcon

5.00/5 (15投票s)

2012年6月16日

CPOL

3分钟阅读

viewsIcon

53483

downloadIcon

2684

本文介绍如何为 WPF Listbox 实现橡皮筋行为。此外,本文还介绍了如何使用 Expression Blend 添加此行为。

介绍 

本文介绍如何为 WPF Listbox 实现橡皮筋行为。此外,本文还介绍了如何使用 Expression Blend 添加此行为。

背景

1. WPF Listbox 的多重选择。

http://msdn.microsoft.com/en-us/library/system.windows.controls.listbox.selectionmode

2. 通过 Expression Blend 添加自定义行为

http://msdn.microsoft.com/en-us/library/ee341397(v=expression.40).aspx 

项目结构

示例项目结构如下:

Project Structure 

Rubberband 项目包含相应的行为。RubberBand 类保存 UI 逻辑以呈现橡皮筋。RubberBandSelection 是包含具有多重选择的 ListBox 的演示项目。

使用代码

让我将本文分成 3 个部分。首先,在 WPF 4.0 中创建自定义行为。然后在 Window 中渲染橡皮筋装饰器。最后,如何在 Expression blend 资源中添加行为以进行重用。

创建自定义行为

行为用于将简单的功能封装到单个组件中,以便于重用。行为可以与任何 WPF 对象关联,以向控件提供额外的行为。行为的示例包括拖放、输入验证、平移和缩放、元素重新定位等……可能的行为列表非常长。

可以通过从 System.Windows.Interactivity.Behavior 类继承来创建自定义行为。

[DescriptionAttribute("Enable Rubberband selection for a WPF listbox object.")]
public class RubberBandBehavior : Behavior<ListBox>
{
        protected override void OnAttached()
        {
            AssociatedObject.Loaded += new System.Windows.RoutedEventHandler(AssociatedObject_Loaded);
            base.OnAttached();
        }
        void AssociatedObject_Loaded(object sender, System.Windows.RoutedEventArgs e)
        {
            RubberBandAdorner band = new RubberBandAdorner(AssociatedObject);
            AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(AssociatedObject);
            adornerLayer.Add(band);
        }
        protected override void OnDetaching()
        {
            AssociatedObject.Loaded -= new System.Windows.RoutedEventHandler(AssociatedObject_Loaded);
            base.OnDetaching();
        }
} 

创建橡皮筋装饰器

通过从 Adorner 类继承来创建橡皮筋装饰器。装饰器是一种特殊的 FrameworkElement,用于向用户提供视觉提示。除了其他用途外,装饰器还可用于向元素添加功能句柄或提供有关控件的状态信息。

装饰器在 AdornerLayer 中呈现,AdornerLayer 是一个始终位于装饰元素或装饰元素集合顶部的呈现表面。装饰器的呈现独立于装饰器绑定的 UIElement 的呈现。装饰器通常使用位于装饰元素左上角的标准二维坐标原点相对于其绑定的元素定位。

public RubberBandAdorner(UIElement adornedElement)
:base(adornedElement)
{
}  

要将装饰器绑定到特定的 UIElement,请按照以下步骤操作

1. 调用静态方法 GetAdornerLayer 以获取要装饰的 UIElement 的 AdornerLayer 对象。GetAdornerLayer 向上遍历可视树,从指定的 UIElement 开始,并返回它找到的第一个装饰器层。(如果未找到装饰器层,该方法将返回 null。)

2. 调用 Add 方法以将装饰器绑定到目标 UIElement。

RubberBandAdorner band = new RubberBandAdorner(AssociatedObject);
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(AssociatedObject);
adornerLayer.Add(band); 

订阅鼠标按下和鼠标移动事件,并获取起点和当前点。使用 OnRender 重写来呈现视觉效果。

protected override void OnRender(DrawingContext drawingContext)
{
     Rect rect = new Rect(startpoint, currentpoint);
     drawingContext.DrawGeometry(brush, new Pen(SystemColors.HighlightBrush, 1), new RectangleGeometry(rect));
     base.OnRender(drawingContext);
} 

基本思想是在移动鼠标时,计算鼠标的当前位置并在 ListBox 上绘制橡皮筋装饰器。可以通过使用 InvalidateVisual() 手动调用 OnRender 重写方法。在每次鼠标移动时,确定橡皮筋矩形内的 listbox 项目并使其被选中。

foreach (var obj in _selector.Items)
{
   ListBoxItem item = _selector.ItemContainerGenerator.ContainerFromItem(obj) as ListBoxItem;
   if (item != null)
   {
       Point point = item.TransformToAncestor(AdornedElement).Transform(new Point(0, 0));
       Rect bandrect = new Rect(startpoint, currentpoint);
       Rect elementrect = new Rect(point.X, point.Y, item.ActualWidth, item.ActualHeight);
       if (bandrect.IntersectsWith(elementrect))
       {
             item.IsSelected = true;
       }
       else
       {
             item.IsSelected = false;
       }
   }
} 

在 Expression Blend 中添加自定义行为

将 RubberBand.dll 复制到以下位置:

C:\Program Files (x86)\Microsoft SDKs\Expression\Blend\.NETFramework\v4.0\Libraries

1. 打开 Expression Blend。

2. 创建一个新的 WPF 项目。

3. 打开“资源”->“行为”面板。您将在列表中找到 RubberBandBehavior。

4. 将行为拖放到设计器中的 Listbox 对象中。确保将 Listbox 的选择模式设置为“多选”或“扩展”。

© . All rights reserved.