绑定button点击一个方法
我有一个datagrid绑定到可观察的对象集合。 我想要做的是有一个button,将执行代表被点击的button行的对象的方法。 所以我现在拥有这样的东西:
<DataGridTemplateColumn Header="Command"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <Button Name="cmdCommand" Click="{Binding Command}" Content="Command"/> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn>
哪个不起作用,并报告以下错误:
Click =“{绑定命令}”无效。 “{绑定命令}”不是有效的事件处理程序方法名称。 只有生成的或代码隐藏类的实例方法才是有效的。
我已经看过命令绑定,但看起来它只是最终转到一个外部命令,而不是绑定到该行的对象。 我已经在代码后面使用事件处理程序工作,然后将其路由到绑定到选定行的项目(因为单击button时选中该行),但似乎是差劲的处理方式,我认为我'我只是在这里错过了一些
我一直这样做。 这里看一个例子,你将如何实现它。
将您的XAML更改为使用button的Command属性而不是Click事件。 我使用SaveCommand这个名字,因为它更容易遵循命令Command。
<Button Command="{Binding Path=SaveCommand}" />
Button所绑定的CustomClass现在需要一个名为SaveCommand的ICommand
types的属性。 它需要指向执行该命令时要运行的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 } }
上面的代码使用了一个RelayCommand,它接受两个参数:要执行的方法,以及如果命令可以执行或不可执行的真/假值。 RelayCommand类是一个单独的.cs文件,其代码如下所示。 我从Josh Smith那里得到了:)
/// <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 }
你有各种各样的可能性。 最简单和最丑陋的是:
XAML
<Button Name="cmdCommand" Click="Button_Clicked" Content="Command"/>
代码在后面
private void Button_Clicked(object sender, RoutedEventArgs e) { FrameworkElement fe=sender as FrameworkElement; ((YourClass)fe.DataContext).DoYourCommand(); }
另一个解决scheme(更好)是在YourClass
上提供一个ICommand属性。 这个命令将有一个对你的YourClass
的引用,因此可以对这个类执行一个动作。
XAML
<Button Name="cmdCommand" Command="{Binding YourICommandReturningProperty}" Content="Command"/>
因为在写这个答案的时候,还发布了很多其他的答案,我不再写更多的答案。 如果您对我所展示的某种方式感兴趣,或者您认为我犯了一个错误,请发表评论。
上面是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类如下所示…
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
希望能帮助任何VB.Net开发者!
点击是一个事件。 在你的代码背后,你需要有一个对应的事件处理程序,无论你在XAML中有什么。 在这种情况下,您需要具备以下条件:
private void Command(object sender, RoutedEventArgs e) { }
命令是不同的。 如果你需要连接一个命令,你可以使用button的Commmand属性,你可以使用一些预先构build的命令或者通过CommandManager类(我认为)连接你自己的命令。
Rachel给出的解决scheme还有更多的解释:
“使用Model-View-ViewModeldevise模式的WPF应用程序”
由约什·史密斯