WPF EventSetter Handler Command

 

最近作一個工具,忽然發現ListBox和ListView等列表控件的MouseDoubleClick事件有時候是獲取不到當前雙擊的行對象數據的,好比這樣寫:html

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

雙擊行就會出現雙擊的對象爲空。express

上一篇文章中已經說明怎麼解決這個問題:ide

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

使用Style中的EventSetter Handler這裏就不在更多介紹。函數

可是今天想要解決的問題是怎麼把EventSetter Handler使用Command綁定的方式把Handler事件進行解耦工具

要使用第三方類庫CommandBehavior(AttachedCommandBehavior acb)進行解耦this

代碼以下:spa

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

<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>code

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

完整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>
View Code
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;
    }
}
View Code

 

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

源代碼下載地址

相關文章
相關標籤/搜索