WPF DataTemplate Событие привязки к функции объекта - PullRequest
2 голосов
/ 04 июня 2010

Я сейчас пишу DataTemplate для моего пользовательского типа, скажем, FootballPlayer. В этом шаблоне я хотел бы поставить т.е. Кнопка и сделать эту кнопку при нажатии вызвать некоторые функции FootballPlayer, например. Run ().

Есть ли какой-нибудь простой или сложный, но чистый способ добиться такого поведения?

Мне кажется, что DataTemplate знает всю информацию о моем объекте, потому что установлен DataType и включено пространство имен clr.

<DataTemplate DataType="{x:Type my:FootballPlayer}">

</DataTemplate>

Полагаю, для этого есть чистый способ. Может кто-нибудь сказать мне, как?

// редактировать Решение не должно быть чистым. Теперь, после некоторого исследования, я просто ищу какое-либо решение, которое может сделать вызов функции / вызвать событие для связываемого объекта.

Ответы [ 2 ]

3 голосов
/ 04 июня 2010

Да, есть чистый способ сделать это. Одним из аспектов использования шаблона Model-View-ViewModel в WPF (не то, что вы должны использовать это) является команда . WPF Командная ссылка

Вот упрощенный, но понятный и довольно безопасный для типов каркасный класс для предоставления команд из объекта источника данных:

using System;
using System.Windows.Input;

namespace MVVM
{
/// <summary>
/// Defines a command that can be bound to from XAML and redirects to a handler function.
/// </summary>
public class ViewModelCommand : ICommand
{
    private Action _handler;


    public ViewModelCommand(Action handler)
    {
        _handler = handler;
    }


    #region ICommand Members

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public event EventHandler CanExecuteChanged;

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

    #endregion
}

/// <summary>
/// Defines a command that can be bound to from XAML and redirects to a handler function.
/// </summary>
public class ViewModelCommand<T> : ICommand
    where T : class
{
    private Action<T> _handler;


    public ViewModelCommand(Action<T> handler)
    {
        _handler = handler;
    }


    #region ICommand Members

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter)
    {
        _handler(parameter as T);
    }

    #endregion
}
}

Ваш источник данных (например, класс FootballPlayer) затем предоставляет свойство команды следующим образом:

    /// <summary>
    /// Tell the player to run.  This particular command takes a string as a parameter.
    /// </summary>
    public ICommand RunCommand
    {
        get { return new ViewModelCommand<string>(run); }
    }

Функция реализации в том же классе FootballPlayer может выглядеть следующим образом:

    /// <summary>
    /// Tell the player to run.  This particular command takes a string as a parameter.
    /// </summary>
    public void search(string destination)
    {
        System.Windows.MessageBox.Show(destination, "Running to destination...");
    }

Наконец, ваш XAML имеет следующую привязку данных:

<Button Content="{Binding PlayerName}" FontSize="16" CommandParameter="{Binding Text, ElementName=txtDestination}" Command="{Binding RunCommand, Source={StaticResource ViewModelDataSource}}" />

(Поскольку вы используете DataTemplate, источники привязок должны быть скорректированы; но в этом суть. Я с большим успехом использовал это в проекте класса - это позволило очень четко разделить логика и интерфейс.)

1 голос
/ 08 декабря 2010

Если вы установите общий обработчик для события: <Button Click="FootballPlayer_Run"/>, DataContext для e.OriginalSource будет объектом FootballPlayer, который используется для привязки.Затем вы можете вызвать Run для этого объекта.

private void FootballPlayer_Run(object sender, RoutedEventArgs e)
        {
            FrameworkElement ele = e.OriginalSource as FrameworkElement;
            if (ele != null)
            {
                FootballPlayer fp = ele.DataContext as FootballPlayer;
                if (fp != null)
                {
                    fp.Run();
                }
            }
            e.Handled = true;
        }
...