【问题标题】:wpf bind event or command to function on item data contextwpf 绑定事件或命令以在项目数据上下文上运行
【发布时间】:2017-11-20 20:14:27
【问题描述】:

我有一些看起来像这样的 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 的某些视图模型。感觉应该是可能的,因为数据是以这种方式绑定的,但我还没有找到关于如何做到这一点的描述。

【问题讨论】:

  • @Hampus 让我明白。当鼠标进入控件时,您想执行 WhenMouseMove 中包含的内容吗?
  • @DanieleSartori 不,当鼠标在 ListBoxItem 内移动时
  • 你说的“不是先通过”是什么意思?您需要编写一些代码在某处调用调用 WhenMouseMove 方法。
  • @mm8 我试图不弄乱后面的代码,或者如果我有一个模型视图,那么使用事件处理程序来确定触发事件的项目的数据上下文是什么然后调用它

标签: c# wpf xaml


【解决方案1】:

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

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

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

// xaml 文件

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

// 视图模型(MyItem 类)

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

【讨论】:

  • 可能有效,但我似乎无法包含我猜此代码需要的交互
  • 添加对 System.Windows.Interactivity dll 的引用(如果安装了 Blend 或 VS2015,则由系统定义)然后添加以下命名空间 xmlns:i="schemas.microsoft.com/expression/2010/interactivity"
猜你喜欢
  • 2011-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多