Wpf 绑定按钮单击一个方法

Wpf 绑定按钮单击一个方法,wpf,Wpf,我有一个绑定到可观察对象集合的数据网格。我想做的是有一个按钮,它将执行表示被单击按钮行的对象的方法。所以我现在得到的是这样的东西: <DataGridTemplateColumn Header="Command"> <DataGridTemplateColumn.CellTemplate> <DataTemplate>

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

            <DataGridTemplateColumn Header="Command">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Button Name="cmdCommand" Click="{Binding Command}" 
                                Content="Command"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>

它不工作并报告以下错误:

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


我已经研究了命令绑定,但看起来它只会转到单个外部命令,而不是绑定到行的对象。我让它在代码背后使用事件处理程序,然后将其路由到绑定到选定行的项目(因为单击按钮时该行被选中),但这似乎是一种糟糕的处理方式,我认为我只是缺少了一些东西。

单击是一个事件。在代码隐藏中,需要有一个对应于XAML中所有内容的事件处理程序。在这种情况下,您需要具备以下条件:

private void Command(object sender, RoutedEventArgs e)
{

}

命令是不同的。如果需要连接命令,可以使用按钮的Commmand属性,或者使用一些预构建的命令,或者通过CommandManager类连接自己的命令(我想)。

我一直都在这样做。下面是一个示例,以及您将如何实现它

将XAML更改为使用按钮的Command属性,而不是单击事件。我使用名称SaveCommand,因为它比名为Command的命令更容易执行

<Button Command="{Binding Path=SaveCommand}" />
上面的代码使用一个RelayCommand,它接受两个参数:要执行的方法,以及命令是否可以执行的真/假值。RelayCommand类是一个单独的.cs文件,其代码如下所示。我从乔希·史密斯那里得到的:)

//
///一种命令,其唯一目的是
///将其功能传递给其他用户
///通过调用委托创建对象。这个
///CanExecute的默认返回值
///方法为“true”。
/// 
公共类中继命令:ICommand
{
#区域字段
只读操作_执行;
只读谓词_canExecute;
#endregion//字段
#区域构造函数
/// 
///创建始终可以执行的新命令。
/// 
///执行逻辑。
公共中继命令(操作执行)
:此(执行,空)
{
}
/// 
///创建一个新命令。
/// 
///执行逻辑。
///执行状态逻辑。
公共RelayCommand(操作执行,谓词canExecute)
{
if(execute==null)
抛出新的ArgumentNullException(“执行”);
_执行=执行;
_canExecute=canExecute;
}
#endregion//构造函数
#区域ICommand成员
[调试步骤至]
公共布尔CanExecute(对象参数)
{
return _canExecute==null?true:_canExecute(参数);
}
公共事件事件处理程序CanExecuteChanged
{
添加{CommandManager.RequerySuggested+=value;}
删除{CommandManager.RequerySuggested-=value;}
}
公共void执行(对象参数)
{
_执行(参数);
}
#endregion//ICommand成员
}

您有各种可能性。最简单、最丑陋的是:

XAML

<Button Name="cmdCommand" Click="Button_Clicked" Content="Command"/> 
<Button Name="cmdCommand" Command="{Binding YourICommandReturningProperty}" Content="Command"/>

另一个解决方案(更好)是在
YourClass
上提供ICommand属性。此命令已经引用了
YourClass
-对象,因此可以在此类上执行操作

XAML

<Button Name="cmdCommand" Click="Button_Clicked" Content="Command"/> 
<Button Name="cmdCommand" Command="{Binding YourICommandReturningProperty}" Content="Command"/>



因为在写这个答案的过程中,很多其他的答案都被贴出来了,所以我不再写更多的了。如果你对我展示的方式感兴趣,或者你认为我犯了错误,请发表评论

Rachel已经给出了解决方案的更多解释:

“具有模型视图模型设计模式的WPF应用程序”

乔希·史密斯


这是上面Rachel答案的VB.Net版本

显然,XAML绑定是相同的

<Button Command="{Binding Path=SaveCommand}" />

您的自定义类将如下所示

''' <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
“”
''检索新的或现有的RelayCommand。
''' 
''“[中继命令]
公共只读属性SaveCommand()作为ICommand
得到
如果_saveCommand为空,则
_saveCommand=New RelayCommand(函数(参数)SaveObject(),函数(参数)CanSave())
如果结束
返回保存命令
结束
端属性
Private\u将命令另存为ICommand
''' 
''返回布尔标志,指示是否可以执行命令。
''' 
'''[布尔]
私有函数CanSave()为布尔值
'验证命令可以在此处执行。
返回真值
端函数
''' 
执行命令时要运行的“”代码。
''' 
已将“”转换为VB.net中的函数,以避免“表达式不生成值”错误。
''''[没什么]
私有函数SaveObject()
'保存命令执行逻辑。
一无所获
端函数
最后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
公共类RelayCommand:实现ICommand
只读\u作为动作执行(对象的)
只读\u可以作为谓词执行(对象的)
私有事件ICommand\u CanExecuteChanged作为EventHandler实现ICommand.CanExecuteChanged
''' 
''创建一个始终可以执行的新命令。
''' 
''执行逻辑。
Public Sub New(作为动作执行(对象))
Me.New(执行,无)
端接头
''' 
''创建一个新命令。
''' 
''执行逻辑。
''执行状态逻辑。
Public Sub New(作为动作(对象的)执行,canExecute作为谓词(对象的))
如果执行什么都不是,那么
抛出新ArgumentNullException(“执行”)
如果结束
_执行
_canExecute=ca
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
<Button Margin="0,10,0,0" 
                    Text="Access galery"
                    Clicked="OpenGalery"
                    BackgroundColor="{StaticResource Primary}"
                    TextColor="White" />
private async void OpenGalery(object sender, EventArgs e) 
{
//do your bidding
}