【问题标题】:InvokeCommandAction isn't invoking the templatebindingInvokeCommandAction 没有调用模板绑定
【发布时间】:2015-04-07 19:18:48
【问题描述】:

我正在尝试制作一个可重用的控件,该控件显示由 TemplateBinding 绑定的图像,并且是交互式的,最终通过与视图模型绑定的命令支持右键单击、中间单击、左键单击等内容。它还将支持多个叠加层,因此该控件继承自 ItemsControl。

但是 SomeViewModel 的 MouseLeftButtonDownCommand 没有被调用。我在 Generic.xaml 中编写了一些测试 ChangePropertyAction,它确实正确地触发了动作,所以这是我在命令连接时做错的事情。

这是代码(抱歉这么长)

在我的主题\Generic.xaml 中

<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Custom_ContentControl"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions">


<Style TargetType="{x:Type local:CustomControl}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:CustomControl}">
                <Grid Background="Red">
                    <i:Interaction.Triggers>
                        <i:EventTrigger EventName="MouseLeftButtonDown">
                            <i:InvokeCommandAction Command="{TemplateBinding MouseLeftButtonDownCommand}" />
                            <!--<ei:ChangePropertyAction TargetName="Image" PropertyName="Visibility" Value="Collapsed" />-->
                        </i:EventTrigger>
                    </i:Interaction.Triggers>
                    <Image x:Name="Image" Source="{TemplateBinding ImageSource}" Stretch="Fill" />
                    <ItemsPresenter />
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

在我的 CustomControl.cs 中

namespace Custom_ContentControl
{
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

public class CustomControl : ItemsControl
{
    static CustomControl()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomControl), new FrameworkPropertyMetadata(typeof(CustomControl)));
    }

    public static readonly DependencyProperty ImageSourceProperty = DependencyProperty.Register(
        "ImageSource", typeof(ImageSource), typeof(CustomControl), new PropertyMetadata(default(ImageSource)));

    public ImageSource ImageSource
    {
        get { return (ImageSource)GetValue(ImageSourceProperty); }
        set { SetValue(ImageSourceProperty, value); }
    }

    public static readonly DependencyProperty MouseLeftButtonDownCommandProperty = DependencyProperty.Register(
        "MouseLeftButtonDownCommand", typeof (ICommand), typeof (CustomControl), new PropertyMetadata(default(ICommand)));

    public ICommand MouseLeftButtonDownCommand
    {
        get { return (ICommand) GetValue(MouseLeftButtonDownCommandProperty); }
        set { SetValue(MouseLeftButtonDownCommandProperty, value); }
    }
}
}

在我的 MainWindow.xaml 中

<Window x:Class="Custom_ContentControl.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" 
    mc:Ignorable="d" 
    xmlns:customContentControl="clr-namespace:Custom_ContentControl"
    Title="MainWindow" Height="350" Width="525" 
    d:DataContext="{d:DesignInstance customContentControl:SomeViewModel}">
<Grid>
    <customContentControl:CustomControl ImageSource="Resources/sample.jpg"
                                        MouseLeftButtonDownCommand="{Binding MouseLeftButtonDownCommand}">
        <!--<TextBlock Text="Some sample text" Foreground="White" />-->
    </customContentControl:CustomControl>
</Grid>

在我的 MainWindow.xaml.cs 中

namespace Custom_ContentControl
{
using System.Windows;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;

public partial class MainWindow
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new SomeViewModel();
    }
}

class SomeViewModel : ViewModelBase
{
    private RelayCommand mouseLeftButtonDownCommand;

    public RelayCommand MouseLeftButtonDownCommand
    {
        get { return mouseLeftButtonDownCommand ?? (mouseLeftButtonDownCommand = new RelayCommand(OnMouseLeftButtonDown)); }
    }

    private void OnMouseLeftButtonDown()
    {
        MessageBox.Show("Button clicked");
    }
}
}

请注意,此项目依赖于 MvvmLight nuget 包以及 Expression.Blend.Sdk。

如何正确连接我的 ViewModel 命令,以便通过鼠标左键单击来调用它?

【问题讨论】:

    标签: c# wpf xaml custom-controls interactive


    【解决方案1】:

    您只需将 Generic.xaml 中的 Binding 稍微更改为

    <i:Interaction.Triggers>
       <i:EventTrigger EventName="MouseLeftButtonDown">
           <i:InvokeCommandAction Command="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=MouseLeftButtonDownCommand}" />
       </i:EventTrigger>
    </i:Interaction.Triggers>
    

    这现在将正确绑定到您的 CustomControl 中的依赖属性 希望对你有帮助

    【讨论】:

    • 确实有帮助,非常感谢。你知道为什么TemplateBinding 不能与EventTrigger 一起使用吗?因为如果我在带有&lt;Button Width="100" Height="25" Command="{TemplateBinding MouseLeftButtonDownCommand}" /&gt; 的图像之后添加一个按钮,则按钮命令会按预期连接。
    • 是的,这将在触发 ViewModel 命令时起作用,因为 MainWindow 的 DataContext 是 ViewModel,它调用 ViewModel 命令而不是 CustomControls MouseLeftButtonDown DependencyProperty。 EventTrigger 在两个场景中触发,但只有第一个被您的 CustomControl DP 拾取。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-07
    • 2018-11-12
    • 2013-11-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多