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

Silverlight:使用行为启用滑块上的鼠标滚轮

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.90/5 (6投票s)

2010年7月7日

Ms-PL

7分钟阅读

viewsIcon

43178

downloadIcon

1207

自定义行为,为 Silverlight 滑块启用鼠标滚轮支持以及更多功能

您可能需要解除对以下路径中某些 DLL 文件的锁定

  • MouseWheelApp\MouseWheelApp\Bin\Debug
  • MouseWheelApp\MouseWheelBehaviorLibrary\Bin\Debug

在线应用
感谢 Adefwebserver 托管我的应用程序

引言

本文将逐步介绍如何创建两个简单的行为 (behaviors),以便为 Silverlight 目前尚不支持的滑块 (Slider) 控件启用鼠标滚轮 (MouseWheel) 功能。本文也将是对行为的简单介绍。

问题

Silverlight 的 Slider 控件不支持鼠标滚轮。虽然有一个可以监听的 MouseWheel 事件,但在 Blend 中它不会暴露 Delta 值,该值用于判断滚轮是向上还是向下滚动。为 Slider 添加鼠标支持的一种方法是使用后台代码,但这不如使用行为那样能给设计人员自由,也不具备可重用性。

曾尝试使用 ChangePropertyAction,但无法获取鼠标值。这限制了设计人员完成工作的能力。

我的解决方案

我制作了两种不同的行为来启用鼠标滚轮支持,这些行为使用在 Slider 上设置的属性以获得一些灵活性。这些属性是:MaximumMinimumSmallChangeValue。目的是允许设计人员设置边界,以及在滚动鼠标滚轮时值应增加多少。

超越滑块

虽然这是一个针对 Slider 控件的行为,但它的用途不止于此。因为 Slider 包含了设置 MaximumMinimumSmallChange 的属性,所以它非常适合绑定你的属性并设置边界。这最初是为它所关联的任何对象(具有数字属性和边界)提供鼠标滚轮支持而设计的,因此它也可以通过一些绑定来为其他控件设置鼠标滚轮功能。它还通过使用行为避免了后台代码。例如,视频播放器上的音量控制,你可以将音量值绑定到 Slider 的值,并将我的行为关联到视频播放器上,这样用户当鼠标在播放器上方时就可以通过鼠标滚轮调节音量。或者通过鼠标滚轮调整图像或窗口的大小,并隐藏滑块

基本示例

在深入研究代码之前,我想先概述一下它能做什么,这样你可以决定是否要继续阅读。

在这个我们将在本文中创建的应用里,我们有一个矩形 (rectangle) 和三个滑块 (sliders)。每个滑块都附加了一个简单的行为,以启用鼠标滚轮支持。除此之外,我还将另一个行为附加到矩形上,当鼠标在矩形上时,它将响应鼠标滚轮事件。这个行为将改变其中一个滑块的值。

代码

首先创建一个新的 Silverlight 应用程序,并将其命名为类似 MouseWheelApp 的名称,这个应用将使用这些行为。然后选择在新网站中托管 Silverlight 应用程序

现在添加一个新项目,选择 Silverlight 类库,并将其命名为 MouseWheelBehaviorLibrary

MouseWheelBehaviorLibrary 添加对 System.Windows.Interactivity 的引用。这个 DLL 来自 Microsoft Expression Blend SDK

MouseWheelBehaviorLibrary 项目中,添加一个新类并将其命名为 EnableSliderMouseWheel

EnableSliderMouseWheel.cs

  1. 添加 using 语句
    using System.Windows.Interactivity;
  2. 让类继承自
    public class EnableSliderMouseWheel : Behavior<Slider>

    该类继承自 Behavior,并将其泛型设置为 Slider 控件。通过将类型设置为 Slider,它将限制此行为可以附加的对象。对于这个行为,我想创建一个简单的,它只在附加时或设计人员将其拖放到控件上时启用鼠标滚轮支持。

  3. 现在粘贴以下代码
    protected override void OnAttached()
            {
                base.OnAttached();
    
                //attach event handler on mouse wheel event
                AssociatedObject.MouseWheel += 
            new MouseWheelEventHandler(SliderMouseScroll_MouseWheel);
            }

    行为“附加”到控件时,这段代码会运行。AssociatedObject 代表它所附加的对象,在我们的例子中是一个 Slider 控件。我们正在为 MouseWheel 事件添加一个事件处理程序。(此时代码会报错,我稍后会展示 SliderMouseScroll_MouseWheel 方法。)基本上,一旦行为附加到滑块上,它就会添加事件处理程序来操纵滑块的值。

  4. 再次粘贴以下代码
    protected override void OnDetaching()
    {
          base.OnDetaching();
    
          //remove event handler on mouse wheel event
          AssociatedObject.MouseWheel -= 
            new MouseWheelEventHandler(SliderMouseScroll_MouseWheel);
    }

    这与上面的代码相反,当它被分离时,它会移除它附加的事件处理程序。

  5. 现在粘贴行为的核心部分,即鼠标滚动时触发的方法。
        void SliderMouseScroll_MouseWheel(object sender, MouseWheelEventArgs e)
            {
                //Delta = how much the wheel was scrolled. + for up - for down
    
                //check to see if Delta is positive.
                if (e.Delta > 0)
                {
                    //using small change of Target(slider) property. 
                    //this allows how much value can change from the designer
                    //
                    //alternatively you can actually use the delta value instead
                    //of forcing small change increments.
    
                    AssociatedObject.Value = AssociatedObject.Value + 
    					AssociatedObject.SmallChange;
                }
                else //same as above just backwards
                {
                    //using small change of Target(slider) property. 
                    //this allows how much value can change from the designer
                    //
                    //alternatively you can actually use the delta value instead
                    //of forcing small change increments.
    
                    AssociatedObject.Value = AssociatedObject.Value - 
    					AssociatedObject.SmallChange;
                }
            }    

首先我检查 Delta 值,它表示鼠标滚动的距离和方向。如果是正数,则表示向上滚动,负数则表示向下滚动。我只用 Delta 来检查方向。接下来我获取滑块的值,并加上或减去滑块SmallChange 值。通过使用 SmallChange,我允许设计人员设置它应该改变多少。

我没有任何检查来判断它是否会超过或低于边界,这是因为它已经内置了这些检查。

我们的第一个行为完成了。现在我们将开始制作上面展示的示例。

使用行为的应用

下一步是设置一个将使用此行为的应用程序。

  1. 添加引用到上一步生成的 DLL 或 MouseWheelBehaviorLibrary。只需转到 MouseWheelBehaviorLibrary 项目的 bin 目录并选择 MouseWheelBehaviorLibrary.dll
  2. Blend 中打开 MouseWheelAppMainPage.xaml。(右键单击并选择“在 Expression Blend 中打开”)

    确保我们已经有了这个行为

  3. 重新创建一个类似这样的界面(矩形、3 个滑块、用作标签的文本块)。确保矩形的值没有设置为 Auto,否则将不允许在下一步中进行绑定。滑块和标签位于一个网格中。

  4. Slider 的值绑定到 Rectangle 的属性。确保是双向 (two-way) 绑定。接下来,将 MaximumMinimumSmallChange 设置为适合你项目的值。注意 OpacityMaximum 应该为 1。

  5. 将我们创建的行为附加到滑块上并运行。现在,当你在滑块上滚动鼠标时,它会改变值。(只需将行为拖放到滑块上即可。)

更灵活的行为

下一个行为更进一步。它可以附加到任何控件,并且当鼠标在附加的控件上时,它将响应鼠标滚轮。如前所述,这可以用于为其他控件添加鼠标滚轮支持。(因为它与前一个几乎相同,我将简要地介绍一些已解释过的细节。)

  1. 和之前的行为一样,我们需要在库中创建一个新类。添加一个名为 EnableMouseWheel.cs 的新类。添加 using
    using System.Windows.Interactivity;
  2. 继承自 TargetedTriggerAction<slider><T>,为 T 使用 Slider。同时实现 Invoke 方法或复制该方法。
    public class EnableMouseWheel : TargetedTriggerAction<Slider>
        {
            //this method is required for the base class
            protected override void Invoke(object parameter)
            {
    
            }
        }

    这里的 Invoke 方法我们什么都不做。这种类型的行为可以附加到任何东西上,而泛型 <T> 可以让你指定一个目标类。Target 用于访问另一个控件。对于我们的例子,我们将其设置为 Slider,这样当鼠标滚轮滚动时,行为将改变目标Slider”的值。

  3. 复制以下代码
            protected override void OnAttached()
            {
                base.OnAttached();
    
                //add event handler to mouse wheel event
                ((FrameworkElement)AssociatedObject).MouseWheel += 
    		new MouseWheelEventHandler(SliderMouseScroll_MouseWheel);
            }
    
            protected override void OnDetaching()
            {
                base.OnDetaching();
    
                //remove the event handler
                ((FrameworkElement)AssociatedObject).MouseWheel -= 
    		new MouseWheelEventHandler(SliderMouseScroll_MouseWheel);
            }
    
            //this method runs on Mouse Wheel event
            void SliderMouseScroll_MouseWheel(object sender, MouseWheelEventArgs e)
            {
                //Delta = how much the wheel was scrolled. + for up - for down
    
                //check to see if Delta is positive.
                if (e.Delta > 0)
                {
                    //using small change of Target(slider) property. 
                    //this allows how much value can change from the designer
                    //
                    //alternatively you can actually use the delta value instead
                    //of forcing small change increments.
    
                    Target.Value = Target.Value + Target.SmallChange;
                }
                else //same as above just backwards
                {
                    //using small change of Target(slider) property. 
                    //this allows how much value can change from the designer
                    //
                    //alternatively you can actually use the delta value instead
                    //of forcing small change increments.
    
                    Target.Value = Target.Value - Target.SmallChange;
                }
            }

    这基本上是相同的代码,但有一些改动。当我们附加时,我们会将其转换为 FrameworkElement,它是所有控件的基类。我们需要进行转换,因为它不知道它到底是什么类型。接下来是在事件处理程序中,我们使用的是 Target 而不是 AssociatedObject,这是因为我们想编辑作为 TargetSlider 的值,而不是我们附加到的对象(AssociatedObject)。

  4. 这是一个可选步骤。如果我们看之前检查是否有行为时的截图,你可能注意到没有对该行为的解释。在这里我们将添加它
     [System.ComponentModel.Description("Target : Trigger. 
    	Responds to mousewheel event of attached object when focused. 
    	Manipulates slider values based on slider properties.")]
        public class EnableMouseWheel : TargetedTriggerAction<Slider>
        {

    添加特性 (attribute)。生成并返回到 Blend 中的 Mainpage.xaml

使用行为

  1. 检查我们是否有了行为和描述

  2. 行为附加到矩形上,并在行为的属性中,将 Target 设置为其中一个滑块

  3. 现在运行,当你在矩形上滚动时,它应该会改变滑块。现在你已经完成了。

完整代码

using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

using System.Windows.Interactivity;

namespace MouseWheelBehaviorLibrary
{
    [System.ComponentModel.Description
	("Target : Trigger. Responds to mousewheel event of attached object 
	when focused. Manipulates slider values based on slider properties.")]
    public class EnableMouseWheel : TargetedTriggerAction<Slider>
    {
        //this method is required for the base class
        protected override void Invoke(object parameter)
        {

        }

        protected override void OnAttached()
        {
            base.OnAttached();

            //add event handler to mouse wheel event
            ((FrameworkElement)AssociatedObject).MouseWheel += 
		new MouseWheelEventHandler(SliderMouseScroll_MouseWheel);
        }

        protected override void OnDetaching()
        {
            base.OnDetaching();

            //remove the event handler
            ((FrameworkElement)AssociatedObject).MouseWheel -= 
		new MouseWheelEventHandler(SliderMouseScroll_MouseWheel);
        }

        //this method runs on Mouse Wheel event
        void SliderMouseScroll_MouseWheel(object sender, MouseWheelEventArgs e)
        {
            //Delta = how much the wheel was scrolled. + for up - for down

            //check to see if Delta is positive.
            if (e.Delta > 0)
            {
                //using small change of Target(slider) property. 
                //this allows how much value can change from the designer
                //
                //alternatively you can actually use the delta value instead
                //of forcing small change increments.

                Target.Value = Target.Value + Target.SmallChange;
            }
            else //same as above just backwards
            {
                //using small change of Target(slider) property. 
                //this allows how much value can change from the designer
                //
                //alternatively you can actually use the delta value instead
                //of forcing small change increments.

                Target.Value = Target.Value - Target.SmallChange;
            }
        }
    }
}

/////
/////
/////

using System.Windows.Controls;
using System.Windows.Input;

using System.Windows.Interactivity;

namespace MouseWheelBehaviorLibrary
{
    public class EnableSliderMouseWheel : Behavior<Slider>
    {
        protected override void OnAttached()
        {
            base.OnAttached();

            //attach event handler on mouse wheel event
            AssociatedObject.MouseWheel += new MouseWheelEventHandler
			(SliderMouseScroll_MouseWheel);
        }

        protected override void OnDetaching()
        {
            base.OnDetaching();

            //remove event handler on mouse wheel event
            AssociatedObject.MouseWheel -= new MouseWheelEventHandler
			(SliderMouseScroll_MouseWheel);
        }

        void SliderMouseScroll_MouseWheel(object sender, MouseWheelEventArgs e)
        {
            //Delta = how much the wheel was scrolled. + for up - for down

            //check to see if Delta is positive.
            if (e.Delta > 0)
            {
                //using small change of Target(slider) property. 
                //this allows how much value can change from the designer
                //
                //alternatively you can actually use the delta value instead
                //of forcing small change increments.

                AssociatedObject.Value = AssociatedObject.Value + 
				AssociatedObject.SmallChange;
            }
            else //same as above just backwards
            {
                //using small change of Target(slider) property. 
                //this allows how much value can change from the designer
                //
                //alternatively you can actually use the delta value instead
                //of forcing small change increments.

                AssociatedObject.Value = AssociatedObject.Value - 
					AssociatedObject.SmallChange;
            }
        }
    }
}

注释

我发现 EnableMouseWheel 行为存在一些兼容性问题,主要是在那些已经具有某种鼠标滚轮支持的控件上。Combobox 似乎只有在所选索引为 -1 时才有效,而像 listbox 这样的控件似乎在滚动到列表末尾后才能正常工作。

有关行为的更多信息,请参阅 Silverlight Show

感谢您的阅读,希望这对您有所帮助。这是我的第一篇文章,因此我非常欢迎您对文章或代码提出任何反馈。这是我在 CodeProject 上的第一篇文章。

历史

  • 2010年7月7日:初次发布
© . All rights reserved.