wpf绑定事件或命令以在项数据上下文

时间:2017-11-16 14:18:53

标签: c# wpf xaml

我有一些看起来像这样的WPF代码

C#

namespace ItemEventTest
{
public partial class MainWindow : Window
 {
    public MainWindow()
    {
        DataContext = this;

        MyItems = new ObservableCollection<MyItem>();
        MyItems.Add(new MyItem { Name = "Otto" });
        MyItems.Add(new MyItem { Name = "Dag" });
        MyItems.Add(new MyItem { Name = "Karin" });

        InitializeComponent();
    }

    public ObservableCollection<MyItem> MyItems { get; set; }
}

public class MyItem :INotifyPropertyChanged
{
    private string m_name;

    public string Name
    {
        get { return m_name; }
        set
        {
            m_name = value; 
            OnPropertyChanged();
        }
    }

    public void WhenMouseMove()
    {
        //Do stuff
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
 }
}

的Xaml

<Window x:Class="ItemEventTest.MainWindow"
    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:ItemEventTest"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">
    <Grid>
        <ListBox ItemsSource="{Binding MyItems}">
            <ListBox.ItemTemplate>
                <DataTemplate DataType="local:MyItem">
                    <TextBlock Text="{Binding Name}"/>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</Window>

我现在要做的是当鼠标移动到某个项目上时,要在作为该项目来源的对象上调用WhenMouseMove
我希望直接在对象上调用该函数,而不是首先通过MainWindow或连接到MainWindow的某个视图模型。感觉它应该是可能的,因为数据是这样绑定的,但我还没有设法找到如何做的描述。

1 个答案:

答案 0 :(得分:0)

如果您正在寻找MVVM模式的解决方案

编辑:添加对System.Windows.Interactivity dll的引用(如果安装了Blend或VS2015,则系统定义)

然后添加以下命名空间xmlns:i="schemas.microsoft.com/expression/2010/interactivity‌​"

// xaml file

<Grid>
        <ListBox ItemsSource="{Binding MyItems}">
            <ListBox.ItemTemplate>
                <DataTemplate DataType="local:MyItem">
                    <TextBlock Text="{Binding Name}">
                          <i:Interaction.Triggers>
                <i:EventTrigger EventName="MouseEnter">
                    <i:InvokeCommandAction Command="{Binding MouseHoveredItemChangedCommand}"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
                    </TextBlock>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>

// viewmodel(MyItem class)

  public void WhenMouseMove()
        {
            //Do stuff
            Console.WriteLine(Name);
        }

        private RelayCommand _MouseHoveredItemChangedCommand;
        public RelayCommand MouseHoveredItemChangedCommand
        {
            get
            {
                if (_MouseHoveredItemChangedCommand == null)
                {
                    _MouseHoveredItemChangedCommand = new RelayCommand(WhenMouseMove);
                }
                return _MouseHoveredItemChangedCommand;
            }
        }

// RelayCommand类

 public class RelayCommand : ICommand
        {
            public event EventHandler CanExecuteChanged
            {
                add { CommandManager.RequerySuggested += value; }
                remove { CommandManager.RequerySuggested -= value; }
            }
            private Action methodToExecute;
            private Func<bool> canExecuteEvaluator;
            public RelayCommand(Action methodToExecute, Func<bool> canExecuteEvaluator)
            {
                this.methodToExecute = methodToExecute;
                this.canExecuteEvaluator = canExecuteEvaluator;
            }
            public RelayCommand(Action methodToExecute)
                : this(methodToExecute, null)
            {
            }
            public bool CanExecute(object parameter)
            {
                if (this.canExecuteEvaluator == null)
                {
                    return true;
                }
                else
                {
                    bool result = this.canExecuteEvaluator.Invoke();
                    return result;
                }
            }
            public void Execute(object parameter)
            {
                this.methodToExecute.Invoke();
            }
        }