绑定按钮单击一个方法

Mar*_*ark 49 wpf

我有一个数据网格绑定到一个可观察的对象集合.我想要做的是有一个按钮,它将执行一个对象的方法,该对象表示被点击的按钮行.所以我现在拥有的是这样的:

            <DataGridTemplateColumn Header="Command">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Button Name="cmdCommand" Click="{Binding Command}" 
                                Content="Command"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
Run Code Online (Sandbox Code Playgroud)

哪个不起作用并报告以下错误:

Click ="{Binding Command}"无效.'{Binding Command}'不是有效的事件处理程序方法名称.只有生成的或代码隐藏类上的实例方法才有效.

我看过命令绑定,但看起来它最终会转到单个外部命令而不是绑定到行的对象.我让它在后面的代码上使用事件处理程序,然后将其路由到绑定到所选行的项目(因为在单击按钮时行被选中),但这似乎很难处理这个并且我认为我'我只是遗漏了一些东西.

Rac*_*hel 89

我一直这样做.以下是一个示例以及如何实现它.

更改您的XAML以使用按钮的Command属性而不是Click事件.我使用名称SaveCommand,因为它更容易遵循名为命令的东西.

<Button Command="{Binding Path=SaveCommand}" />
Run Code Online (Sandbox Code Playgroud)

Button现在绑定的CustomClass需要有一个名为SaveCommand的属性ICommand.它需要指向要在执行命令时运行的CustomClass上的方法.

public MyCustomClass
{
    private ICommand _saveCommand;

    public ICommand SaveCommand
    {
        get
        {
            if (_saveCommand == null)
            {
                _saveCommand = new RelayCommand(
                    param => this.SaveObject(), 
                    param => this.CanSave()
                );
            }
            return _saveCommand;
        }
    }

    private bool CanSave()
    {
        // Verify command can be executed here
    }

    private void SaveObject()
    {
        // Save command execution logic
    }
}
Run Code Online (Sandbox Code Playgroud)

上面的代码使用了一个RelayCommand,它接受两个参数:要执行的方法,以及命令是否可以执行的true/false值.RelayCommand类是一个单独的.cs文件,代码如下所示.我是从约什史密斯那里得到的:)

/// <summary>
/// A command whose sole purpose is to 
/// relay its functionality to other
/// objects by invoking delegates. The
/// default return value for the CanExecute
/// method is 'true'.
/// </summary>
public class RelayCommand : ICommand
{
    #region Fields

    readonly Action<object> _execute;
    readonly Predicate<object> _canExecute;        

    #endregion // Fields

    #region Constructors

    /// <summary>
    /// Creates a new command that can always execute.
    /// </summary>
    /// <param name="execute">The execution logic.</param>
    public RelayCommand(Action<object> execute)
        : this(execute, null)
    {
    }

    /// <summary>
    /// Creates a new command.
    /// </summary>
    /// <param name="execute">The execution logic.</param>
    /// <param name="canExecute">The execution status logic.</param>
    public RelayCommand(Action<object> execute, Predicate<object> canExecute)
    {
        if (execute == null)
            throw new ArgumentNullException("execute");

        _execute = execute;
        _canExecute = canExecute;           
    }

    #endregion // Constructors

    #region ICommand Members

    [DebuggerStepThrough]
    public bool CanExecute(object parameters)
    {
        return _canExecute == null ? true : _canExecute(parameters);
    }

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

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

    #endregion // ICommand Members
}
Run Code Online (Sandbox Code Playgroud)

  • 这比我想象的要复杂得多.我如何将其连接到对象中的命令?该类是否需要由绑定对象公开?> (27认同)
  • @Sinaesthetic这是一个事件定义.对于事件,你有`add`和`remove`,就像你对属性有`get`和`set`一样.它只是告诉它在向事件添加或删除方法时要执行的操作. (5认同)
  • +1但是,这可能需要更多解释如何使用. (3认同)
  • HCL:同意,如何将其连接到视图中?在我绑定的对象中如何使用它?似乎这可能是要走的路,但我不知道如何根据我目前的需求实现这一点.谢谢! (2认同)
  • 就像一个注释:这里是关于此代码的缺点的评论.但我不能说对典型用途的影响有多大./sf/ask/159709651/ (2认同)

HCL*_*HCL 27

你有各种各样的可能性.最简单也是最丑陋的是:

XAML

<Button Name="cmdCommand" Click="Button_Clicked" Content="Command"/> 
Run Code Online (Sandbox Code Playgroud)

代码背后

private void Button_Clicked(object sender, RoutedEventArgs e) { 
    FrameworkElement fe=sender as FrameworkElement;
    ((YourClass)fe.DataContext).DoYourCommand();     
} 
Run Code Online (Sandbox Code Playgroud)

另一种解决方案(更好)是在您的网站上提供ICommand属性YourClass.此命令已经引用了您的YourClass-object,因此可以对此类执行操作.

XAML

<Button Name="cmdCommand" Command="{Binding YourICommandReturningProperty}" Content="Command"/>
Run Code Online (Sandbox Code Playgroud)

因为在写这个答案时,发布了很多其他答案,我停止写更多.如果您对我展示的某种方式感兴趣,或者如果您认为我犯了错误,请发表评论.


Füt*_*ire 8

以下是Rachel上面回答的VB.Net演绎.

显然XAML绑定是一样的......

<Button Command="{Binding Path=SaveCommand}" />
Run Code Online (Sandbox Code Playgroud)

您的自定义类看起来像这样......

''' <summary>
''' Retrieves an new or existing RelayCommand.
''' </summary>
''' <returns>[RelayCommand]</returns>
Public ReadOnly Property SaveCommand() As ICommand
    Get
        If _saveCommand Is Nothing Then
            _saveCommand = New RelayCommand(Function(param) SaveObject(), Function(param) CanSave())
        End If
        Return _saveCommand
    End Get
End Property
Private _saveCommand As ICommand

''' <summary>
''' Returns Boolean flag indicating if command can be executed.
''' </summary>
''' <returns>[Boolean]</returns>
Private Function CanSave() As Boolean
    ' Verify command can be executed here.
    Return True
End Function

''' <summary>
''' Code to be run when the command is executed.
''' </summary>
''' <remarks>Converted to a Function in VB.net to avoid the "Expression does not produce a value" error.</remarks>
''' <returns>[Nothing]</returns>
Private Function SaveObject()
    ' Save command execution logic.
   Return Nothing
End Function
Run Code Online (Sandbox Code Playgroud)

最后RelayCommand类如下......

Public Class RelayCommand : Implements ICommand

ReadOnly _execute As Action(Of Object)
ReadOnly _canExecute As Predicate(Of Object)
Private Event ICommand_CanExecuteChanged As EventHandler Implements ICommand.CanExecuteChanged

''' <summary>
''' Creates a new command that can always execute.
''' </summary>
''' <param name="execute">The execution logic.</param>
Public Sub New(execute As Action(Of Object))
    Me.New(execute, Nothing)
End Sub

''' <summary>
''' Creates a new command.
''' </summary>
''' <param name="execute">The execution logic.</param>
''' <param name="canExecute">The execution status logic.</param>
Public Sub New(execute As Action(Of Object), canExecute As Predicate(Of Object))
    If execute Is Nothing Then
        Throw New ArgumentNullException("execute")
    End If
    _execute = execute
    _canExecute = canExecute
End Sub

<DebuggerStepThrough>
Public Function CanExecute(parameters As Object) As Boolean Implements ICommand.CanExecute
    Return If(_canExecute Is Nothing, True, _canExecute(parameters))
End Function

Public Custom Event CanExecuteChanged As EventHandler
    AddHandler(ByVal value As EventHandler)
        AddHandler CommandManager.RequerySuggested, value
    End AddHandler
    RemoveHandler(ByVal value As EventHandler)
        RemoveHandler CommandManager.RequerySuggested, value
    End RemoveHandler
    RaiseEvent(ByVal sender As Object, ByVal e As EventArgs)
        If (_canExecute IsNot Nothing) Then
            _canExecute.Invoke(sender)
        End If
    End RaiseEvent
End Event

Public Sub Execute(parameters As Object) Implements ICommand.Execute
    _execute(parameters)
End Sub

End Class
Run Code Online (Sandbox Code Playgroud)

希望能帮助任何VB.Net开发人员!