array(2) { ["docs"]=> array(10) { [0]=> array(10) { ["id"]=> string(3) "428" ["text"]=> string(77) "Visual Studio 2017 单独启动MSDN帮助(Microsoft Help Viewer)的方法" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(8) "DonetRen" ["tagsname"]=> string(55) "Visual Studio 2017|MSDN帮助|C#程序|.NET|Help Viewer" ["tagsid"]=> string(23) "[401,402,403,"300",404]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400964" ["_id"]=> string(3) "428" } [1]=> array(10) { ["id"]=> string(3) "427" ["text"]=> string(42) "npm -v;报错 cannot find module "wrapp"" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "zzty" ["tagsname"]=> string(50) "node.js|npm|cannot find module "wrapp“|node" ["tagsid"]=> string(19) "[398,"239",399,400]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400760" ["_id"]=> string(3) "427" } [2]=> array(10) { ["id"]=> string(3) "426" ["text"]=> string(54) "说说css中pt、px、em、rem都扮演了什么角色" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(12) "zhengqiaoyin" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400640" ["_id"]=> string(3) "426" } [3]=> array(10) { ["id"]=> string(3) "425" ["text"]=> string(83) "深入学习JS执行--创建执行上下文(变量对象,作用域链,this)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "Ry-yuan" ["tagsname"]=> string(33) "Javascript|Javascript执行过程" ["tagsid"]=> string(13) "["169","191"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511399901" ["_id"]=> string(3) "425" } [4]=> array(10) { ["id"]=> string(3) "424" ["text"]=> string(30) "C# 排序技术研究与对比" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "vveiliang" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(8) ".Net Dev" ["catesid"]=> string(5) "[199]" ["createtime"]=> string(10) "1511399150" ["_id"]=> string(3) "424" } [5]=> array(10) { ["id"]=> string(3) "423" ["text"]=> string(72) "【算法】小白的算法笔记:快速排序算法的编码和优化" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "penghuwan" ["tagsname"]=> string(6) "算法" ["tagsid"]=> string(7) "["344"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511398109" ["_id"]=> string(3) "423" } [6]=> array(10) { ["id"]=> string(3) "422" ["text"]=> string(64) "JavaScript数据可视化编程学习(二)Flotr2,雷达图" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "chengxs" ["tagsname"]=> string(28) "数据可视化|前端学习" ["tagsid"]=> string(9) "[396,397]" ["catesname"]=> string(18) "前端基本知识" ["catesid"]=> string(5) "[198]" ["createtime"]=> string(10) "1511397800" ["_id"]=> string(3) "422" } [7]=> array(10) { ["id"]=> string(3) "421" ["text"]=> string(36) "C#表达式目录树(Expression)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "wwym" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(4) ".NET" ["catesid"]=> string(7) "["119"]" ["createtime"]=> string(10) "1511397474" ["_id"]=> string(3) "421" } [8]=> array(10) { ["id"]=> string(3) "420" ["text"]=> string(47) "数据结构 队列_队列实例:事件处理" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "idreamo" ["tagsname"]=> string(40) "C语言|数据结构|队列|事件处理" ["tagsid"]=> string(23) "["246","247","248",395]" ["catesname"]=> string(12) "数据结构" ["catesid"]=> string(7) "["133"]" ["createtime"]=> string(10) "1511397279" ["_id"]=> string(3) "420" } [9]=> array(10) { ["id"]=> string(3) "419" ["text"]=> string(47) "久等了,博客园官方Android客户端发布" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(3) "cmt" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511396549" ["_id"]=> string(3) "419" } } ["count"]=> int(200) } 222 WPF中 MVVM模式的Slider Binding. - 爱码网

对于Button的Command的绑定可以通过实现ICommand接口来进行,但是Slider并没有Command属性。

另外如果要实现MVVM模式的话,需要将一些Method和Slider的Event进行绑定,如何进行呢?

(对于UIElement的一些Event进行绑定一定有一些通用的方法,目前还没有深入研究。)

 

首先,Slider Value的绑定是很简单的, 绑定Slider的Value属性即可。

(1)ViewModel

    public class SliderViewModel : ViewModelBase
    {
        private string selectedValue;

        public SliderViewModel()
        {

        }

        public string SelectedValue
        {
            get
            {
                return this.selectedValue;
            }
            set
            {
                if (this.selectedValue != value)
                {
                    this.selectedValue = value;
                    base.OnPropertyChanged("SelectedValue"); 
                }
            }
        }
    }

(2) View, 设定 DataContext 为ViewModel, 绑定SelectValue到 Slider的Value 和TextBlock的Text属性上。

这样当拖动Slider时,Slider的值会传给SelectedValue, 然后SelectValue会传给TexBlock上。

 x:Class="WpfApplication2.View.SliderView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:vm="clr-namespace:WpfApplication2.ViewModel"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <UserControl.DataContext>
        <vm:SliderViewModel />
    </UserControl.DataContext>
    <Grid>
        <Slider HorizontalAlignment="Left"
                Margin="28,102,0,0"
                VerticalAlignment="Top"
                Width="158" 
                Minimum="0"
                Maximum="100"
                Value="{Binding SelectedValue}"/>
        <TextBlock HorizontalAlignment="Left"
                   Margin="203,102,0,0"
                   TextWrapping="Wrap"
                   Text="{Binding SelectedValue}"
                   VerticalAlignment="Top" />

    </Grid>
</UserControl>

效果如下:

WPF中 MVVM模式的Slider Binding.

如果不想显示double值,可以设定Slider的属性。

                TickFrequency="1"
                IsSnapToTickEnabled="True"
                TickPlacement="None" />

其次, 当用鼠标或者键盘移动滑块结束的时候,需要进行一些处理。如果不用MVVM的方式的话,可以在Slider的Event里面增加处理。

用MVVM的话,就稍微麻烦一些。

(1)下载或者复制C:\Program Files (x86)\Microsoft SDKs\Expression\Blend\.NETFramework\v4.0\Libraries\System.Windows.Interactivity.dll

        在工程中Reference 这个dll,命名空间里面增加:using System.Windows.Interactivity

 (2)新写个SliderValueChangedBehavior 继承Behavior<Slider>

    /// <summary>
    /// Helps find the user-selected value of a slider only when the keyboard/mouse gesture has ended.
    /// </summary>
    public class SliderValueChangedBehavior : Behavior<Slider>
    {
        /// <summary>
        /// Keys down.
        /// </summary>
        private int keysDown;

        /// <summary>
        /// Indicate whether to capture the value on latest key up.
        /// </summary>
        private bool applyKeyUpValue;

        #region Dependency property Value

        /// <summary>
        /// DataBindable value.
        /// </summary>
        public double Value
        {
            get { return (double)GetValue(ValueProperty); }
            set { SetValue(ValueProperty, value); }
        }

        public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
            "Value",
            typeof(double),
            typeof(SliderValueChangedBehavior),
            new PropertyMetadata(default(double), OnValuePropertyChanged));

        #endregion

        #region Dependency property Value

        /// <summary>
        /// DataBindable Command
        /// </summary>
        public ICommand Command
        {
            get { return (ICommand)GetValue(CommandProperty); }
            set { SetValue(CommandProperty, value); }
        }

        public static readonly DependencyProperty CommandProperty = DependencyProperty.Register(
            "Command",
            typeof(ICommand),
            typeof(SliderValueChangedBehavior),
            new PropertyMetadata(null));

        #endregion

        /// <summary>
        /// On behavior attached.
        /// </summary>
        protected override void OnAttached()
        {
            this.AssociatedObject.KeyUp += this.OnKeyUp;
            this.AssociatedObject.KeyDown += this.OnKeyDown;
            this.AssociatedObject.ValueChanged += this.OnValueChanged;

            base.OnAttached();
        }

        /// <summary>
        /// On behavior detaching.
        /// </summary>
        protected override void OnDetaching()
        {
            base.OnDetaching();

            this.AssociatedObject.KeyUp -= this.OnKeyUp;
            this.AssociatedObject.KeyDown -= this.OnKeyDown;
            this.AssociatedObject.ValueChanged -= this.OnValueChanged;
        }

        /// <summary>
        /// On Value dependency property change.
        /// </summary>
        private static void OnValuePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var me = (SliderValueChangedBehavior)d;
            if (me.AssociatedObject != null)
                me.Value = (double)e.NewValue;
        }

        /// <summary>
        /// Occurs when the slider's value change.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            if (Mouse.Captured != null)
            {
                this.AssociatedObject.LostMouseCapture += this.OnLostMouseCapture;
            }
            else if (this.keysDown != 0)
            {
                this.applyKeyUpValue = true;
            }
            else
            {
                this.ApplyValue();
            }
        }

        private void OnLostMouseCapture(object sender, MouseEventArgs e)
        {
            this.AssociatedObject.LostMouseCapture -= this.OnLostMouseCapture;
            this.ApplyValue();
        }

        private void OnKeyUp(object sender, KeyEventArgs e)
        {
            if (this.keysDown-- != 0)
            {
                this.ApplyValue();
            }
        }

        private void OnKeyDown(object sender, KeyEventArgs e)
        {
            this.keysDown++;
        }

        /// <summary>
        /// Applies the current value in the Value dependency property and raises the command.
        /// </summary>
        private void ApplyValue()
        {
            this.Value = this.AssociatedObject.Value;

            if (this.Command != null)
                this.Command.Execute(this.Value);
        }
    }

 (3) 在View中为Slider的行为添加Command

            <i:Interaction.Behaviors>
                <helper:SliderValueChangedBehavior Command="{Binding ValueChangedCommand}"
                                                  />
            </i:Interaction.Behaviors>

(4)在ViewModel中实现当Slider值个改变的时候进行一些处理。

        public ICommand ValueChangedCommand
        {
            get
            {
                if (this.valueChangedCommmand == null)
                {
                    this.valueChangedCommmand = new RelayCommand(
                        param => this.PopValue(),
                        null);
                }

                return this.valueChangedCommmand; 
            }
        }

        private void PopValue()
        {
            MessageBox.Show(String.Format("Selected value is {0}", this.selectedValue)); 
        }

最后,进行调试,发现ValueChangedCommand当每次Silder值变更的时候都会被执行

那么如何实现最后一次值变更时,才执行Command呢?

 

对于Button的Command的绑定可以通过实现ICommand接口来进行,但是Slider并没有Command属性。

另外如果要实现MVVM模式的话,需要将一些Method和Slider的Event进行绑定,如何进行呢?

(对于UIElement的一些Event进行绑定一定有一些通用的方法,目前还没有深入研究。)

 

首先,Slider Value的绑定是很简单的, 绑定Slider的Value属性即可。

(1)ViewModel

    public class SliderViewModel : ViewModelBase
    {
        private string selectedValue;

        public SliderViewModel()
        {

        }

        public string SelectedValue
        {
            get
            {
                return this.selectedValue;
            }
            set
            {
                if (this.selectedValue != value)
                {
                    this.selectedValue = value;
                    base.OnPropertyChanged("SelectedValue"); 
                }
            }
        }
    }

(2) View, 设定 DataContext 为ViewModel, 绑定SelectValue到 Slider的Value 和TextBlock的Text属性上。

这样当拖动Slider时,Slider的值会传给SelectedValue, 然后SelectValue会传给TexBlock上。

 x:Class="WpfApplication2.View.SliderView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:vm="clr-namespace:WpfApplication2.ViewModel"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <UserControl.DataContext>
        <vm:SliderViewModel />
    </UserControl.DataContext>
    <Grid>
        <Slider HorizontalAlignment="Left"
                Margin="28,102,0,0"
                VerticalAlignment="Top"
                Width="158" 
                Minimum="0"
                Maximum="100"
                Value="{Binding SelectedValue}"/>
        <TextBlock HorizontalAlignment="Left"
                   Margin="203,102,0,0"
                   TextWrapping="Wrap"
                   Text="{Binding SelectedValue}"
                   VerticalAlignment="Top" />

    </Grid>
</UserControl>

效果如下:

WPF中 MVVM模式的Slider Binding.

如果不想显示double值,可以设定Slider的属性。

                TickFrequency="1"
                IsSnapToTickEnabled="True"
                TickPlacement="None" />

其次, 当用鼠标或者键盘移动滑块结束的时候,需要进行一些处理。如果不用MVVM的方式的话,可以在Slider的Event里面增加处理。

用MVVM的话,就稍微麻烦一些。

(1)下载或者复制C:\Program Files (x86)\Microsoft SDKs\Expression\Blend\.NETFramework\v4.0\Libraries\System.Windows.Interactivity.dll

        在工程中Reference 这个dll,命名空间里面增加:using System.Windows.Interactivity

 (2)新写个SliderValueChangedBehavior 继承Behavior<Slider>

    /// <summary>
    /// Helps find the user-selected value of a slider only when the keyboard/mouse gesture has ended.
    /// </summary>
    public class SliderValueChangedBehavior : Behavior<Slider>
    {
        /// <summary>
        /// Keys down.
        /// </summary>
        private int keysDown;

        /// <summary>
        /// Indicate whether to capture the value on latest key up.
        /// </summary>
        private bool applyKeyUpValue;

        #region Dependency property Value

        /// <summary>
        /// DataBindable value.
        /// </summary>
        public double Value
        {
            get { return (double)GetValue(ValueProperty); }
            set { SetValue(ValueProperty, value); }
        }

        public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
            "Value",
            typeof(double),
            typeof(SliderValueChangedBehavior),
            new PropertyMetadata(default(double), OnValuePropertyChanged));

        #endregion

        #region Dependency property Value

        /// <summary>
        /// DataBindable Command
        /// </summary>
        public ICommand Command
        {
            get { return (ICommand)GetValue(CommandProperty); }
            set { SetValue(CommandProperty, value); }
        }

        public static readonly DependencyProperty CommandProperty = DependencyProperty.Register(
            "Command",
            typeof(ICommand),
            typeof(SliderValueChangedBehavior),
            new PropertyMetadata(null));

        #endregion

        /// <summary>
        /// On behavior attached.
        /// </summary>
        protected override void OnAttached()
        {
            this.AssociatedObject.KeyUp += this.OnKeyUp;
            this.AssociatedObject.KeyDown += this.OnKeyDown;
            this.AssociatedObject.ValueChanged += this.OnValueChanged;

            base.OnAttached();
        }

        /// <summary>
        /// On behavior detaching.
        /// </summary>
        protected override void OnDetaching()
        {
            base.OnDetaching();

            this.AssociatedObject.KeyUp -= this.OnKeyUp;
            this.AssociatedObject.KeyDown -= this.OnKeyDown;
            this.AssociatedObject.ValueChanged -= this.OnValueChanged;
        }

        /// <summary>
        /// On Value dependency property change.
        /// </summary>
        private static void OnValuePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var me = (SliderValueChangedBehavior)d;
            if (me.AssociatedObject != null)
                me.Value = (double)e.NewValue;
        }

        /// <summary>
        /// Occurs when the slider's value change.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            if (Mouse.Captured != null)
            {
                this.AssociatedObject.LostMouseCapture += this.OnLostMouseCapture;
            }
            else if (this.keysDown != 0)
            {
                this.applyKeyUpValue = true;
            }
            else
            {
                this.ApplyValue();
            }
        }

        private void OnLostMouseCapture(object sender, MouseEventArgs e)
        {
            this.AssociatedObject.LostMouseCapture -= this.OnLostMouseCapture;
            this.ApplyValue();
        }

        private void OnKeyUp(object sender, KeyEventArgs e)
        {
            if (this.keysDown-- != 0)
            {
                this.ApplyValue();
            }
        }

        private void OnKeyDown(object sender, KeyEventArgs e)
        {
            this.keysDown++;
        }

        /// <summary>
        /// Applies the current value in the Value dependency property and raises the command.
        /// </summary>
        private void ApplyValue()
        {
            this.Value = this.AssociatedObject.Value;

            if (this.Command != null)
                this.Command.Execute(this.Value);
        }
    }

 (3) 在View中为Slider的行为添加Command

            <i:Interaction.Behaviors>
                <helper:SliderValueChangedBehavior Command="{Binding ValueChangedCommand}"
                                                  />
            </i:Interaction.Behaviors>

(4)在ViewModel中实现当Slider值个改变的时候进行一些处理。

        public ICommand ValueChangedCommand
        {
            get
            {
                if (this.valueChangedCommmand == null)
                {
                    this.valueChangedCommmand = new RelayCommand(
                        param => this.PopValue(),
                        null);
                }

                return this.valueChangedCommmand; 
            }
        }

        private void PopValue()
        {
            MessageBox.Show(String.Format("Selected value is {0}", this.selectedValue)); 
        }

最后,进行调试,发现ValueChangedCommand当每次Silder值变更的时候都会被执行

那么如何实现最后一次值变更时,才执行Command呢?

相关文章: