Подтвердить что ты не робот

Кнопка привязки Нажмите на метод

У меня есть datagrid, связанный с наблюдаемым набором объектов. То, что я хочу сделать, это кнопка, которая будет выполнять метод объекта, представляющий строку кнопки, которая была нажата. Итак, у меня теперь есть что-то вроде этого:

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

Что не работает и сообщает следующую ошибку:

Click = "{Binding Command}" недействителен. '{Binding Command}' не является допустимым именем метода обработчика события. Действительны только методы экземпляров в сгенерированном или закодированном коде.

Я посмотрел на привязку к командам, но похоже, что это просто приведет к одной внешней команде, а не к объекту, связанному с этой строкой. У меня есть работа с обработчиком событий позади кода, а затем маршрутизация его на элемент, привязанный к выбранной строке (поскольку строка выбирается при нажатии кнопки), но это похоже на плохой способ передачи этого, и я предполагаю, m просто чего-то не хватает.

4b9b3361

Ответ 1

Я делаю это все время. Здесь рассмотрим пример и как вы его реализуете.

Измените свой XAML, чтобы использовать свойство Command вместо кнопки Click. Я использую имя SaveCommand, потому что это проще, чем когда-либо, то что-то с именем Command.

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

В вашем 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
    }
}

В приведенном выше коде используется 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
}

Ответ 2

У вас есть различные возможности. Самый простой и самый уродливый:

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();     
} 

Еще одно решение (лучше) - предоставить свойство ICommand на вашем YourClass. Эта команда будет уже ссылаться на ваш YourClass -объект и поэтому может выполнить действие над этим классом.

XAML

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

Потому что во время написания этого ответа было опубликовано много других ответов, я перестаю писать больше. Если вас интересует один из способов, которые я показал, или, если вы считаете, что я допустил ошибку, сделайте комментарий.

Ответ 3

Вот версия 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!

Ответ 4

Нажмите событие. В вашем коде позади должен быть соответствующий обработчик событий, который вы имеете в XAML. В этом случае вам нужно будет иметь следующее:

private void Command(object sender, RoutedEventArgs e)
{

}

Команды разные. Если вам нужно подключить команду, вы должны использовать свойство Commmand для кнопки, и вы либо будете использовать некоторые готовые команды, либо подключите свой собственный через класс CommandManager (я думаю).

Ответ 5

Еще несколько пояснений к решению, которое Рейчел уже дала:

"Приложения WPF с шаблоном проектирования Model-View-ViewModel"

Джош Смит

http://msdn.microsoft.com/en-us/magazine/dd419663.aspx