c# - 绑定(bind)到 WPF MVVM 中的鼠标事件

标签 c# wpf mvvm

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

我有一个简单的Canvas三个圆圈。执行了一个减小圆半径的命令。这在绑定(bind)到 Button 的命令属性时可以正常工作。 .

不幸的是,当我尝试将此命令绑定(bind)到 PreviewMouseDown Canvas 的事件,它不再起作用了。我错过了什么?

这是 MainWindow.xaml:

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

MainWindow.xaml.cs 是空的,除了根据 MVVM 原则进行初始化:
using System.Windows;

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

这是 ViewModel.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;
    }
}

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

还有一个简单的 RelayCommand.cs 类:
using System;
using System.Windows.Input;

namespace Test
{
    public class ButtonCommand : ICommand
    {
        private Action WhattoExecute;
        private Func<bool> WhentoExecute;
        public ButtonCommand(Action What, Func<bool> When)
        {
            WhattoExecute = What;
            WhentoExecute = When;
        }
        public bool CanExecute(object parameter)
        {
            return WhentoExecute();
        }
        public void Execute(object parameter)
        {
            WhattoExecute();
        }

        public event EventHandler CanExecuteChanged;
    }
}

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

最佳答案

您忘记设置 SourceBinding :

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

关于c# - 绑定(bind)到 WPF MVVM 中的鼠标事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51786858/

相关文章:

c# - RavenDB 嵌入了 Raven Management Studio?

c# - 有没有办法强制 Microsoft.Jet.OLEDB 从 Excel 中获取 MM/DD/YYYY 格式的日期列?

wpf - 您如何在大型项目中组织 WPF 资源?

wpf - 以编程方式为 DataGrid 中的行分配颜色

jquery - 如何在不使用对话框的情况下创建一个看起来像 jQuery 对话框的 div?

c# - ListView SelectedItem 未使用模板 10 UWP 在 MVVM 应用程序中触发

c# - 使用itextsharp将图像设置为pdf中的水印的问题

c# - 如何验证 mvc 模型中列表中的项目数

wpf - 如何在 WPF DependencyProperty 检索上放置断点?

WPF MVVM 将 ComboBox 绑定(bind)到 Datagrid 所选项目