C# - 多个 UIElement 类型集合上的单击事件

Posted

技术标签:

【中文标题】C# - 多个 UIElement 类型集合上的单击事件【英文标题】:C# - Click event on multiple UIElement types collection 【发布时间】:2017-05-03 01:31:30 【问题描述】:

我在画布中显示了一组不同类型的 UI 元素(矩形和图像)。两者都派生自 UIElement 类型。

<ItemsControl ItemsSource="Binding UiElementsCollection">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas HorizontalAlignment="Left" VerticalAlignment="Top">
            </Canvas>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>

一切都显示得很好,但我希望有一个事件触发鼠标事件 - 当我在画布上单击/拖动特定元素时,我想接收这个对象(矩形或图像)。我想做MVVM模式。我该怎么做?

【问题讨论】:

【参考方案1】:

您可以实现一个附加行为,将源集合中所有 UIElement 的 PreviewMouseLeftButtonDown 连接到视图模型的命令:

public class MyBehavior

    public static readonly DependencyProperty MouseLeftButtonDownCommandProperty
        = DependencyProperty.RegisterAttached("MouseLeftButtonDownCommand",
            typeof(ICommand), typeof(MyBehavior), new FrameworkPropertyMetadata(new PropertyChangedCallback(OnMouseLeftButtonDownCommandPropertyChanged)));

    public static void SetMouseLeftButtonDownCommand(UIElement element, ICommand value)
    
        element.SetValue(MouseLeftButtonDownCommandProperty, value);
    
    public static ICommand GetMouseLeftButtonDownCommand(UIElement element)
    
        return (ICommand)element.GetValue(MouseLeftButtonDownCommandProperty);
    

    private static void OnMouseLeftButtonDownCommandPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    
        UIElement element = d as UIElement;
        element.PreviewMouseLeftButtonDown += Element_MouseLeftButtonDown;
    

    private static void Element_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    
        UIElement element = sender as UIElement;
        ICommand command = GetMouseLeftButtonDownCommand(element);
        if (command != null)
            command.Execute(element);
    

查看:

<Window x:Class="WpfApplication1.Window6"
        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:WpfApplication1"
        mc:Ignorable="d"
        Title="Window6" Height="300" Width="300">
    <Window.DataContext>
        <local:ViewModel />
    </Window.DataContext>
    <Grid>
        <ItemsControl ItemsSource="Binding UiElementsCollection">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <Canvas HorizontalAlignment="Left" VerticalAlignment="Top">
                    </Canvas>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemContainerStyle>
                <Style>
                    <Setter Property="local:MyBehavior.MouseLeftButtonDownCommand" 
                            Value="Binding DataContext.TheCommand, RelativeSource=RelativeSource AncestorType=Window" />
                </Style>
            </ItemsControl.ItemContainerStyle>
        </ItemsControl>
    </Grid>
</Window>

查看模型:

public class ViewModel

    public ObservableCollection<UIElement> UiElementsCollection  get;  = new ObservableCollection<UIElement>()
        
            new Button  Content = "btn" ,
            new Border  Background = Brushes.Yellow, Width = 10, Height = 10 
        ;

    public ICommand TheCommand  get;  = new DelegateCommand<UIElement>(element =>
    
        MessageBox.Show(element.GetType().ToString());
    );

您显然需要 ICommand 接口的实现。 DelegateCommand 类在 Prism 中可用:https://github.com/PrismLibrary/Prism/blob/master/Source/Prism/Commands/DelegateCommand.cs

命令对于 MVVM 应用程序非常重要,因此您可能已经知道这一点。关于如何在 MVVM 中使用命令处理事件的更多信息,您可以参考以下博文:https://blog.magnusmontin.net/2013/06/30/handling-events-in-an-mvvm-wpf-application/

【讨论】:

以上是关于C# - 多个 UIElement 类型集合上的单击事件的主要内容,如果未能解决你的问题,请参考以下文章

C#方法输入输出集合中的多个泛型类型

使用 c# 在 Windows Store App 中裁剪和保存图像(UIElement)

澄清 C# 字典上的读写

C#泛型集合之——列表

wpf使用C#控件

C#的集合类型及使用技巧