在WPF MVVM中绑定到鼠标事件

时间:2018-08-10 12:44:45

标签: c# wpf mvvm

我尝试使用System.Windows.Interactivity将屏幕上元素的鼠标事件绑定到某些命令逻辑。

我有一个简单的Canvas,带有三个圆圈。实现了减小圆弧半径的命令。将其绑定到Button的command属性时,效果很好。

不幸的是,当我尝试将此命令绑定到PreviewMouseDown的{​​{1}}事件时,它不再起作用。我想念什么?

这是MainWindow.xaml:

Canvas

MainWindow.xaml.cs为空,但根据MVVM原理进行初始化除外:

<Window x:Class="Test.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
    xmlns:test="clr-namespace:Test"
    Title="MainWindow" Height="550" Width="525">
<Window.Resources>
    <test:ViewModel x:Key="viewobj"/>
</Window.Resources>
<Grid>
    <ItemsControl ItemsSource="{Binding CircleItems, Source={StaticResource viewobj}}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas Background="Black" ClipToBounds="True" HorizontalAlignment="Left" Height="400" Margin="50,20,0,0" VerticalAlignment="Top" Width="400">
                    <i:Interaction.Triggers>
                        <i:EventTrigger EventName="PreviewMouseDown" >
                            <i:InvokeCommandAction Command="{Binding StartCommand}" />
                        </i:EventTrigger>
                    </i:Interaction.Triggers>
                </Canvas>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemContainerStyle>
            <Style TargetType="ContentPresenter">
                <Setter Property="Canvas.Left" Value="{Binding X}"/>
                <Setter Property="Canvas.Top" Value="{Binding Y}"/>
            </Style>
        </ItemsControl.ItemContainerStyle>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Ellipse Width="{Binding Radius}" Height="{Binding Radius}" Fill="Red"/>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
    <Button Content="Button" Command="{Binding StartCommand, Source={StaticResource viewobj}}" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75" Margin="189,474,0,0"/>
</Grid>
</Window>

这是ViewModel.cs:

using System.Windows;

namespace Test
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }
}

CircleItem.cs类:

using System.Collections.ObjectModel;
using System.ComponentModel;
using Test.Model;

namespace Test
{
    public class ViewModel : INotifyPropertyChanged
    {
        public ObservableCollection<CircleItem> CircleItems { get; set; }

        private ButtonCommand _StartCommand;
        public ButtonCommand StartCommand
        {
            get { return _StartCommand; }
        }

        public ViewModel()
        {
            _StartCommand = new ButtonCommand(UpdateMap, () => {return true;});
            CircleItems = new ObservableCollection<CircleItem>();
            CircleItems.Add(new CircleItem(20, 20, 40));
            CircleItems.Add(new CircleItem(60, 60, 50));
            CircleItems.Add(new CircleItem(120, 100, 30));
        }

        public void UpdateMap()
        {
            CircleItem.UpdateMap(CircleItems);
        }

        internal void RaisePropertyChanged(string prop)
        {
            if (PropertyChanged != null)
            { PropertyChanged(this, new PropertyChangedEventArgs(prop)); }
        }
        public event PropertyChangedEventHandler PropertyChanged;
    }
}

还有一个简单的RelayCommand.cs类:

using System.Collections.ObjectModel;
using System.ComponentModel;

namespace Test.Model
{
    public class CircleItem : INotifyPropertyChanged
    {
        private double _x;
        public double X
        {
            get { return _x; }
            set
            {
                if (_x != value)
                {
                    _x = value;
                    RaisePropertyChanged("X");
                }
            }
        }

        private double _y;
        public double Y
        {
            get { return _y; }
            set
            {
                if (_y != value)
                {
                    _y = value;
                    RaisePropertyChanged("Y");
                }
            }
        }

        private double _radius;
        public double Radius
        {
            get { return _radius; }
            set
            {
                if (_radius != value)
                {
                    _radius = value;
                    RaisePropertyChanged("Radius");
                }
            }
        }

        public CircleItem(double x, double y, double radius)
        {
            this.X = x;
            this.Y = y;
            this.Radius = radius;
        }

        public static void UpdateMap(ObservableCollection<CircleItem> coll)
        {
            foreach (var item in coll)
            {
                item.Radius -= 1;
            }
        }

        internal void RaisePropertyChanged(string prop)
        {
            if (PropertyChanged != null)
            { PropertyChanged(this, new PropertyChangedEventArgs(prop)); }
        }
        public event PropertyChangedEventHandler PropertyChanged;
    }
}

请注意,必须安装NuGet程序包“ System.Windows.Interactivity v4.0 for WPF”,此示例才能正常工作。

1 个答案:

答案 0 :(得分:1)

您忘记设置Source中的Binding

<Canvas Background="Black" ClipToBounds="True" HorizontalAlignment="Left" Height="400" Margin="50,20,0,0" VerticalAlignment="Top" Width="400">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="PreviewMouseDown">
            <i:InvokeCommandAction Command="{Binding StartCommand, Source={StaticResource viewobj}}" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
</Canvas>