代码之家  ›  专栏  ›  技术社区  ›  Thern

绑定到WPF MVVM中的鼠标事件

  •  0
  • Thern  · 技术社区  · 7 年前

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

    我有一个简单的 Canvas 有三个圆圈。实现了一个减小圆半径的命令。当绑定到 Button .

    不幸的是,当我试图将此命令绑定到 PreviewMouseDown 事件 帆布 ,它不再工作了。我错过了什么?

    这里是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”才能使此示例正常工作。

    1 回复  |  直到 7 年前
        1
  •  1
  •   mm8    7 年前

    你忘了设置 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>