WPF EventSetter Handler Command

最近做一个工具,突然发现ListBox和ListView等列表控件的MouseDoubleClick事件有时候是获取不到当前双击的行对象数据的,比如这样写:

 <ListBox Grid.Row="1" ItemsSource="{Binding DataList}"
                 MouseDoubleClick="ListBox_MouseDoubleClick"
                 SelectedItem="{Binding CurrentSelectItem}" Background="AliceBlue">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <DockPanel Height="50"  Background="DarkGray" Width="300">
                        <TextBox Text="{Binding Name}"  Height="30" Width="200" Background="DimGray"></TextBox>
                    </DockPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

 private void ListBox_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            ListBox listBox = sender as ListBox;
            if (listBox == null || listBox.SelectedItem == null)
            {
                MessageBox.Show("ListBox1双击对象为空...");
            }
            else
            {
                var model = listBox.SelectedItem as ListBoxModel;
                MessageBox.Show("当前对象为" + model.Name + "  " + model.Age);
            }
        }

双击行就会出现双击的对象为空。

上一篇文章中已经说明怎么解决这个问题:

http://www.cnblogs.com/ligl/p/5629802.html

使用Style中的EventSetter Handler这里就不在更多介绍。

但是今天想要解决的问题是怎么把EventSetter Handler使用Command绑定的方式把Handler事件进行解耦

要使用第三方类库CommandBehavior(AttachedCommandBehavior acb)进行解耦

代码如下:

引用    xmlns:localCommand="clr-namespace:AttachedCommandBehavior"

<Style x:Key="listBox2Item" TargetType="ListBoxItem">
<Style.Setters>
<Setter Property="localCommand:CommandBehavior.Event" Value="MouseDoubleClick"></Setter>
<Setter Property="localCommand:CommandBehavior.Command" Value="{Binding DataContext.DoubleCommand,RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type local:WinTest}}}"></Setter>
<Setter Property="localCommand:CommandBehavior.CommandParameter" Value="{Binding RelativeSource={RelativeSource Self}}"></Setter>
</Style.Setters>
</Style>

ViewModel代码如下

  public class ViewModel : INotifyPropertyChanged
    {
        public ViewModel()
        {
            for (int i = 0; i < 5; i++)
            {
                DataList.Add(new ListBoxModel() { Name = "张三" + i.ToString(), Age = 1000 + i });
                DataList2.Add(new ListBoxModel() { Name = "李四" + i.ToString(), Age = 100 + i });
            }
            doubleCommand = new SimpleCommand(obj =>
            {
                ListBoxItem listBoxItem = obj as ListBoxItem;
                if (listBoxItem != null)
                {
                    ListBoxModel model = listBoxItem.Content as ListBoxModel;
                    if (model != null)
                    {
                        CurrentSelectItem2 = model;
                        MessageBox.Show("Command Banding" + model.Name + "  " + model.Age);
                    }
                }
                //wpftest.ViewModel
                MessageBox.Show("Cmd...");
            }, o => true);
        }

        public SimpleCommand DoubleCommand
        {
            get
            {
                return doubleCommand;
            }

            set
            {
                doubleCommand = value;
                //OnPropertyChanged(new PropertyChangedEventArgs("DoubleCommand"));
            }
        }

        private ObservableCollection<ListBoxModel> dataList = new ObservableCollection<ListBoxModel>();

        private ObservableCollection<ListBoxModel> _dataList2 = new ObservableCollection<ListBoxModel>();

        private ListBoxModel _CurrentSelectItem;

        private ListBoxModel _CurrentSelectItem2;

        private SimpleCommand doubleCommand;

        public ObservableCollection<ListBoxModel> DataList
        {
            get
            {
                return dataList;
            }

            set
            {
                dataList = value;
            }
        }

        /// <summary>
        /// 当前双击的对象
        /// </summary>
        public ListBoxModel CurrentSelectItem
        {
            get
            {
                return _CurrentSelectItem;
            }

            set
            {
                _CurrentSelectItem = value;
                OnPropertyChanged(new PropertyChangedEventArgs("CurrentSelectItem"));
            }
        }

        /// <summary>
        /// ListBox2双击的对象
        /// </summary>
        public ListBoxModel CurrentSelectItem2
        {
            get
            {
                return _CurrentSelectItem2;
            }

            set
            {
                _CurrentSelectItem2 = value;
                OnPropertyChanged(new PropertyChangedEventArgs("CurrentSelectItem2"));
            }
        }

        public ObservableCollection<ListBoxModel> DataList2
        {
            get
            {
                return _dataList2;
            }

            set
            {
                _dataList2 = value;
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, e);
            }
        }
    }

完整Xaml和CS代码如下:

<Window x:Class="WpfTest.WinTest"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfTest"
        xmlns:localCommand="clr-namespace:AttachedCommandBehavior"
        mc:Ignorable="d"
      Title="WinTest" Height="800" Width="800">
    <Window.Resources>
        <Style TargetType="TextBlock">
            <Style.Setters>
                <Setter Property="FontSize" Value="20"></Setter>
            </Style.Setters>
        </Style>

        <Style  TargetType="Button">
            <Style.Setters>
                <Setter Property="localCommand:CommandBehavior.Event" Value="MouseDoubleClick"></Setter>
                <Setter Property="localCommand:CommandBehavior.Command" Value="{Binding DoubleCommand}"></Setter>
                <Setter Property="localCommand:CommandBehavior.CommandParameter" Value="{Binding Path=DataContext, RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type local:WinTest}}}"></Setter>
            </Style.Setters>
        </Style>

        <Style x:Key="listBox2Item" TargetType="ListBoxItem">
            <Style.Setters>
                <Setter Property="localCommand:CommandBehavior.Event" Value="MouseDoubleClick"></Setter>
                <Setter Property="localCommand:CommandBehavior.Command" Value="{Binding DataContext.DoubleCommand,RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type local:WinTest}}}"></Setter>
                <Setter Property="localCommand:CommandBehavior.CommandParameter" Value="{Binding RelativeSource={RelativeSource Self}}"></Setter>
            </Style.Setters>
        </Style>
        <!--<Style x:Key="listBox2Item" TargetType="ListBoxItem">
            <Style.Setters>
                <EventSetter Event="MouseDoubleClick" Handler="ListBox2_MouseDoubleClick"></EventSetter>
            </Style.Setters>
        </Style>-->
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="30"></RowDefinition>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <StackPanel Orientation="Horizontal">
            <StackPanel Margin="0 0 20 0">
                <TextBlock Text="{Binding CurrentSelectItem.Name}"></TextBlock>
                <TextBlock Text="{Binding CurrentSelectItem.Age}"></TextBlock>
            </StackPanel>

            <StackPanel>
                <TextBlock Text="{Binding CurrentSelectItem2.Name}">
                </TextBlock>
                <TextBlock Text="{Binding CurrentSelectItem2.Age}"></TextBlock>
            </StackPanel>

            <Button Content="DoubleClick" ></Button>
        </StackPanel>

        <ListBox Grid.Row="1" ItemsSource="{Binding DataList}"
                 MouseDoubleClick="ListBox_MouseDoubleClick"
                 SelectedItem="{Binding CurrentSelectItem}" Background="AliceBlue">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <DockPanel Height="50"  Background="DarkGray" Width="300">
                        <TextBox Text="{Binding Name}"  Height="30" Width="200" Background="DimGray"></TextBox>
                    </DockPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

        <ListBox Grid.Row="2" ItemsSource="{Binding DataList2}"
                 SelectedItem="{Binding CurrentSelectItem2}"
                 ItemContainerStyle="{StaticResource listBox2Item}"
                  Background="Silver">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <DockPanel Height="50"  Background="DarkOrange" Width="300">
                        <TextBox Text="{Binding Name}"  Height="30" Width="200" Background="DarkCyan"></TextBox>
                    </DockPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</Window>

using AttachedCommandBehavior;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace WpfTest
{
    /// <summary>
    /// WinTest.xaml 的交互逻辑
    /// </summary>
    public partial class WinTest : Window
    {
        ViewModel VModel = new ViewModel();
        public WinTest()
        {
            InitializeComponent();

            this.DataContext = VModel;
        }

        private void ListBox_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            ListBox listBox = sender as ListBox;
            if (listBox == null || listBox.SelectedItem == null)
            {
                MessageBox.Show("ListBox1双击对象为空...");
            }
            else
            {
                var model = listBox.SelectedItem as ListBoxModel;
                MessageBox.Show("当前对象为" + model.Name + "  " + model.Age);
            }
        }

        private void ListBox2_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            ListBoxItem listBoxItem = sender as ListBoxItem;
            if (listBoxItem == null)
            {
                MessageBox.Show("ListBox2双击对象为空...");
            }
            else
            {

                ListBoxModel model = listBoxItem.Content as ListBoxModel;
                if (model != null)
                {
                    VModel.CurrentSelectItem2 = listBoxItem.Content as ListBoxModel;
                    MessageBox.Show(model.Name + "  " + model.Age);
                }

            }
        }

    }

    public class ViewModel : INotifyPropertyChanged
    {
        public ViewModel()
        {
            for (int i = 0; i < 5; i++)
            {
                DataList.Add(new ListBoxModel() { Name = "张三" + i.ToString(), Age = 1000 + i });
                DataList2.Add(new ListBoxModel() { Name = "李四" + i.ToString(), Age = 100 + i });
            }
            doubleCommand = new SimpleCommand(obj =>
            {
                ListBoxItem listBoxItem = obj as ListBoxItem;
                if (listBoxItem != null)
                {
                    ListBoxModel model = listBoxItem.Content as ListBoxModel;
                    if (model != null)
                    {
                        CurrentSelectItem2 = model;
                        MessageBox.Show("Command Banding" + model.Name + "  " + model.Age);
                    }
                }
                //wpftest.ViewModel
                MessageBox.Show("Cmd...");
            }, o => true);
        }

        public SimpleCommand DoubleCommand
        {
            get
            {
                return doubleCommand;
            }

            set
            {
                doubleCommand = value;
                //OnPropertyChanged(new PropertyChangedEventArgs("DoubleCommand"));
            }
        }

        private ObservableCollection<ListBoxModel> dataList = new ObservableCollection<ListBoxModel>();

        private ObservableCollection<ListBoxModel> _dataList2 = new ObservableCollection<ListBoxModel>();

        private ListBoxModel _CurrentSelectItem;

        private ListBoxModel _CurrentSelectItem2;

        private SimpleCommand doubleCommand;

        public ObservableCollection<ListBoxModel> DataList
        {
            get
            {
                return dataList;
            }

            set
            {
                dataList = value;
            }
        }

        /// <summary>
        /// 当前双击的对象
        /// </summary>
        public ListBoxModel CurrentSelectItem
        {
            get
            {
                return _CurrentSelectItem;
            }

            set
            {
                _CurrentSelectItem = value;
                OnPropertyChanged(new PropertyChangedEventArgs("CurrentSelectItem"));
            }
        }

        /// <summary>
        /// ListBox2双击的对象
        /// </summary>
        public ListBoxModel CurrentSelectItem2
        {
            get
            {
                return _CurrentSelectItem2;
            }

            set
            {
                _CurrentSelectItem2 = value;
                OnPropertyChanged(new PropertyChangedEventArgs("CurrentSelectItem2"));
            }
        }

        public ObservableCollection<ListBoxModel> DataList2
        {
            get
            {
                return _dataList2;
            }

            set
            {
                _dataList2 = value;
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, e);
            }
        }
    }

    public class ListBoxModel : INotifyPropertyChanged
    {
        /// <summary>
        /// 姓名
        /// </summary>
        private string _Name;

        /// <summary>
        /// 年龄
        /// </summary>
        private int _Age;

        public string Name
        {
            get
            {
                return _Name;
            }

            set
            {
                _Name = value;
                OnPropertyChanged(new PropertyChangedEventArgs("Name"));
            }
        }

        public int Age
        {
            get
            {
                return _Age;
            }

            set
            {
                _Age = value;
                OnPropertyChanged(new PropertyChangedEventArgs("Age"));
            }
        }

        public void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, e);
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }
}

<Setter Property="localCommand:CommandBehavior.Command" Value="{Binding DataContext.DoubleCommand,RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type local:WinTest}}}"></Setter>

关于这个Command的Value绑定要使用FindAncestor进行查找才能解决,不然是绑定不到ViewModel中的DoubleCommand

发个图看看:

关于CommandBehavior代码可以在

http://download.csdn.net/download/doncle000/7029327 下载使用

国外博客http://marlongrech.wordpress.com/2008/12/04/attachedcommandbehavior-aka-acb/

对于SimpleCommad.cs的源文件我增加了两个参数的构造函数:

 public SimpleCommand(Action<object> execute, Predicate<object> canExecute)
        {
            if (execute == null)
                throw new ArgumentNullException("execute");
            CanExecuteDelegate = canExecute;
            ExecuteDelegate = execute;
        }

源代码下载地址

时间: 2024-10-22 21:55:28

WPF EventSetter Handler Command的相关文章

WPF事件转Command示例

using System.Windows; using System.Windows.Input; namespace TestLauncher.Tools { internal class DragDropHelper { public static readonly DependencyProperty DropCommandProperty; static DragDropHelper() { //Drop DropCommandProperty = DependencyProperty.

WPF - EventSetter

WPF中添加Event 1. ListBox中添加Event <ListBox x:Name="itemsControl" BorderThickness="0" ContextMenuService.IsEnabled="{Binding IsContextMenuOpen,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" ScrollViewer.HorizontalScrollBarV

WPF中的Command命令详解

在WPF中使用命令的步骤很简单 1.创建命令 2.绑定命令 3.设置命令源 4.设置命令目标 WPF中命令的核心是System.Windows.Input.ICommand接口,所有命令对象都实现了此接口.当创建自己的命令时,不能直接实现ICommand接口,而是要使用System.Windows.Input.RouteCommand类,该类已经实现了ICommand接口,所有WPF命令都是RouteCommand类的实例.在程序中处理的大部分命令不是RoutedCommand对象,而是Rout

WPF Event 在 Command 中的应用初级篇,支持所有Event 展示松耦合设计的全部代码 - 解决TextBoxBase.TextChanged或者TextBox.TextChanged等类似事件绑定问题。

做过WPF开发的人,都知道做MVVM架构,最麻烦的是Event的绑定,因为Event是不能被绑定的,同时现有的条件下,命令是无法替代Event.而在开发过程中无法避免Event事件,这样MVVM的架构就不能完全实现了. 所以后来微软提供了一个折中的方案,使用Trigger触发器和System.Windows.Interactivity结合通过事件绑定事件,个人觉得这个方法也挺可以的. 还有Prism框架方法,我看过但是这个方法比较繁琐可用性不高. 后来通过搜索和自己研究知道了一个解决方案,可以绑

WPF命令(Command)介绍、命令和数据绑定集成应用

要开始使用命令,必须做三件事: 一:定义一个命令 二:定义命令的实现 三:为命令创建一个触发器 WPF中命令系统的基础是一个相对简单的ICommand的接口,代码如下: public interface ICommand { event EventHandler CanExecuteChanged; bool CanExecute(object parameter); void Execute(object parameter); } CanExecute用于确定命令是否处于可执行的状态.典型的

WPF中的Command

Command的意义: 在开发过程当中,会有很多按钮需要实现同样的功能.因此可以采用Command将很多操作绑定到统一逻辑. 可以通过CanExecute能够实现禁用/启用控件 Command的四个主要概念 Command Command Source Command Target Command Binding Command: 是要执行的操作.通过ICommand接口实现(方法:Execute/CanExecute,事件:CanExecuteChange)注:Command本身不包含处理逻辑

WPF MVVM,Prism,Command Binding

1.添加引用Microsoft.Practices.Prism.Mvvm.dll,Microsoft.Practices.Prism.SharedInterfaces.dll: 2.新建文件夹,View,ViewModel,View中添加新项FirstView.XAML(Window页面),在ViewModel中添加新项FirstViewModel.CS(类): 3.在FirstView.xaml.cs的构造函数中添加  DataContext=new FirstViewModel(); 4.在

WPF自定义命令Command

一.自定义命令 自定义命令必须要实现ICommand接口,如下代码所示: /// <summary> /// 自定义的清除命令.光脚丫思考 2014-7-31 06:51:32 /// </summary> public class ClearCommand : ICommand { public bool CanExecute(object parameter) { throw new NotImplementedException(); } /// <summary>

WPF中的Command事件绑定

在项目中使用Command绑定能够使我们的代码更加的符合MVVM模式.不了解的同学可能不清楚,只有继承自ButtonBase类的元素才可以直接绑定Command(Button.CheckBox.RadioButton等) <Button Content="Normal" Command="{Binding NormalEventCommand}" ></Button> 如果我们要处理Label或者其他的一些控件,那么只能在走事件: <L