WPF DataTemplate 事件绑定到对象函数

发布于 2024-09-04 02:16:55 字数 431 浏览 4 评论 0原文

我目前正在为我的自定义类型(比如 FootballPlayer)编写 DataTemplate。在此模板中我想放置 ie.按钮并让该按钮在单击时调用一些 FootballPlayer 函数,例如。跑步()。

有没有简单或复杂但干净的方法来实现这种行为?

我相信 DataTemplate 知道有关我的对象的所有信息,因为设置了 DataType 并且包含了 clr-namespace。

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

</DataTemplate>

我想有一种干净的方法可以实现这一目标。谁能告诉我怎么做?

//编辑 解决方案不必是干净的。现在,经过一番调查后,我只是在寻找任何可以调用函数/在被绑定的对象上引发事件的解决方案。

I'm currently writing DataTemplate for my custom type lets say FootballPlayer. In this template I would like to put ie. Button and make that button when clicked call some of FootballPlayer functions eg. Run().

Is there any simple or complex, but clean way to achieve this kind of behaviour?

The DataTemplate I believe is aware of all the information about my object because DataType is set and clr-namespace is included.

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

</DataTemplate>

I suppose there is a clean way to achieve this. Can anyone tell me how?

//edit
The solution doesn't have to be clean. Now, after some investigation I'm just looking for any solution that can make a call to function / raise an event on the object being bound.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

墨离汐 2024-09-11 02:16:55

是的,有一种干净的方法可以做到这一点。在 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,因此需要调整绑定的源;但这就是它的要点。我在一个类项目中使用了它并取得了巨大成功 - 它允许逻辑和 UI 之间非常清晰的分离。)

Yes, there is a clean way to do this. One aspect of using the Model-View-ViewModel pattern in WPF (not that you have to use this) is commanding. WPF Commanding reference

Here is a simplistic but clean and fairly type-safe framework class for exposing commands from your data source object:

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
}
}

Your data source (e.g., FootballPlayer class) then exposes a command property as follows:

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

The implementation function, in the same FootballPlayer class, can then look like this:

    /// <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...");
    }

Finally, your XAML has the following databinding:

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

(Since you're using a DataTemplate, the sources of the bindings would need to be adjusted; but that's the gist of it. I've used this with great success in a class project - it allowed a very clean separation between the logic and the UI.)

葬シ愛 2024-09-11 02:16:55

如果您为事件设置通用处理程序:
<按钮点击=“FootballPlayer_Run”/>
e.OriginalSource 的 DataContext 将是用于绑定的 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;
        }

If you set up a generic handler for the event:
<Button Click="FootballPlayer_Run"/>
the DataContext of the e.OriginalSource will be the FootballPlayer object that is used for binding. You can then call Run on that object.

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;
        }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文