wpf WPF中自定义控件模板的点击事件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26476724/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 12:37:55  来源:igfitidea点击:

Click event of template of a Custom Control in WPF

c#wpfeventswpf-controlscustom-controls

提问by Alexandre Severino

I have created a custom ContentControl in WPF and applied to it the following template:

我在 WPF 中创建了一个自定义 ContentControl 并将以下模板应用于它:

<Style TargetType="{x:Type local:BdlUserControl}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:BdlUserControl">
                <Grid x:Name="ContentGrid">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="22"/>
                        <RowDefinition Height="1*"/>
                    </Grid.RowDefinitions>

                    <Grid Grid.Row="0" Background="White">
                        <StackPanel HorizontalAlignment="Right">
                            <Button Content="Close" Width="50" Name="BtClose" Click="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BtClose_Click}"/>
                        </StackPanel>
                    </Grid>

                    <Grid Grid.Row="1">
                        <ContentPresenter Content="{TemplateBinding Content}" Margin="{TemplateBinding Padding}"/>
                    </Grid>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

The problem is that the BtClose doesn't call the method BtClose_Click declared in the code-behind of the custom control as shown below:

问题是 BtClose 没有调用自定义控件的代码隐藏中声明的方法 BtClose_Click 如下所示:

    public void BtClose_Click(object sender, RoutedEventArgs e)
    {
        Console.WriteLine("Test");
    }

The error is very generic:

该错误非常普遍:

A first chance exception of type 'System.Windows.Markup.XamlParseException' occurred in PresentationFramework.dll

Any hints on why is that happening?

关于为什么会发生这种情况的任何提示?

采纳答案by sa_ddam213

In WPF you can only bind to a DependencyProperty, In WPF Bottons have a Command property that you can Bind to. Commands are the MVVM way to handle events in WPF.

在 WPF 中,您只能绑定到DependencyProperty,在 WPF 中,Bottons 有一个可以绑定到的 Command 属性。命令是在 WPF 中处理事件的 MVVM 方式。

Here is a quick example of a Command binding in WPF.

这是 WPF 中命令绑定的快速示例。

Xaml:

Xml:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="50" Width="100" >
    <Grid>
        <Button Content="Click" Command="{Binding MyCommand}" />
    </Grid>
</Window>

Code:

代码:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        MyCommand = new MyClickCommand();
        InitializeComponent();
        DataContext = this;
    }

    public MyClickCommand MyCommand { get; set; }
}

public class MyClickCommand : ICommand 
{
    public bool CanExecute(object parameter) 
    {
        return true;
    }
    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter)
    {
        MessageBox.Show("click!");
    }
}

In the above example the Executemethod in MyClickCommandwill be called when you click on the button.

在上面的示例中,当您单击按钮时ExecuteMyClickCommand将调用in 方法。

Now to make this a bit more user friendly you can use a RelayCommandimplementations, this allows to pass delegates into the Command implementation which in most cases is the easiest way to use commands in WPF.

现在为了使这更加用户友好,您可以使用RelayCommand实现,这允许将委托传递到命令实现中,这在大多数情况下是在 WPF 中使用命令的最简单方法。

Example:

例子:

Xaml:

Xml:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="50" Width="100" >
    <Grid>
        <Button Content="Click" Command="{Binding MyCommand}" />
    </Grid>
</Window>

Code:

代码:

public partial class MainWindow : Window 
{
    public MainWindow()
    {
        MyCommand = new RelayCommand(MyMethod);
        InitializeComponent();
        DataContext = this;
    }

    public RelayCommand MyCommand { get; set; }

    private void MyMethod()
    {
        MessageBox.Show("Click!");
    }
}

public class RelayCommand : ICommand
{
    readonly Action<object> _execute;
    readonly Func<bool> _canExecute;

    public RelayCommand(Action execute) : this(execute, null) { }
    public RelayCommand(Action<object> execute) : this(execute, null) { }
    public RelayCommand(Action execute, Func<bool> canExecute)
    {
        if (execute == null)
            throw new ArgumentNullException("execute");

        _execute = p => execute();
        _canExecute = canExecute;
    }

    public RelayCommand(Action<object> execute, Func<bool> canExecute)
    {
        if (execute == null)
            throw new ArgumentNullException("execute");

        _execute = execute;
        _canExecute = canExecute;
    }

    public bool CanExecute(object parameter)
    {
        return _canExecute == null ? true : _canExecute();
    }

    public event EventHandler CanExecuteChanged 
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    public void Execute(object parameter)
    {
        _execute(parameter);
    }
}

Example:

例子: