WPF - 将事件绑定到 Item Control 中 Item 的类方法

本文关键字:Item Control 类方法 事件 绑定 WPF | 更新日期: 2023-09-27 18:33:53

我对WPF/XAML有点陌生(尽管我已经学过C#(,非常感谢对我的问题的任何帮助。我确实浏览了其他帖子并谷歌了一段时间,但我似乎找不到令人满意或详细的答案来让我继续我的项目。详情请看下文。提前谢谢你!

目的

我有一个名为 Tile 的类,它由几个属性和一个事件处理程序组成。我还有一个 ItemControl,它有一个按钮(如 DataTemplate(,其 ItemSource 是磁贴的集合。

现在,我想绑定按钮的"Click"事件,以便调用在类 Tile 中定义的事件处理程序方法。

换句话说,当我单击 ItemControl 中任何项的按钮时,必须调用相应 Tile 实例(来自集合(的方法处理程序。我将如何解决这个问题?

以下是整个代码,为避免分心而简化:

XAML

<Window x:Class="SampleWPF.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="300" Width="300">
    <!-- Make a ItemControl for "Tile"s. -->
    <ItemsControl x:Name="TileList">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <!-- Wire the click event of this Button 
                 to event handler in the Tile class. -->
                <Button Content="Show"></Button>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Window>

代码隐藏

namespace SampleWPF
{
    public partial class MainWindow : Window
    {
        ObservableCollection<Tile> tiles;
        public MainWindow()
        {
            InitializeComponent();
            // Adding some sample data for testing.
            tiles = new ObservableCollection<Tile>();
            tiles.Add(new Tile("Item 1"));
            tiles.Add(new Tile("Item 2"));
            TileList.ItemsSource = tiles;
        }
    }
    public class Tile : INotifyPropertyChanged
    {
        public string Data
        { /* Accessors and PropertyNotifiers */ }
        public Tile(string data)
        { /* Initializing and assigning "Data" */ }
        // INotifyPropertyChanged implementation...
        // { ... }
        // This event handler should be bound to the Button's "Click" event
        // in the DataTemplate of the Item.
        public void ShowButton_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Viewing item from: " + this.Data);
        }
    }
}

因此,如果我单击第一个"显示"按钮,输出应该是"查看来自:项目 1 的项目",如果我单击第二个"显示"按钮,输出应该是"查看来自:项目 2 的项目"。

那么推荐/有效的方法是什么呢?我的代码是否不适合此要求?

WPF - 将事件绑定到 Item Control 中 Item 的类方法

事件处理程序是错误的方法 - 使用Commands,更重要的是MVVM。

正如我所看到的,你是新手(可能来自WinFormsASP.NET背景(,你应该阅读这个博客以了解你的想法需要如何改变 - 这是在处理WPF之前要了解的最重要的部分:http://rachel53461.wordpress.com/2012/10/12/switching-from-winforms-to-wpfmvvm/

您还应该阅读 Kent Boogart 关于 MVVM 如何从基本原则工作的博客:http://kentb.blogspot.co.uk/2009/03/view-models-pocos-versus.html

让我从一些基础知识开始:不要在代码中分配 itemsource 隐藏 - 像这样使用绑定:

<Controll ItemSource="{Binding MyObservableCollection}"/>

您可以通过多种方式实现此目的。我认为使用这个。数据不是最好的解决方案。例如,如果你的尾巴有 ID 或其他东西,你可以把这个 id 分配给按钮命令参数,如下所示

<Button CommanParameter="{Binding Path=ID}" Click="ShowButton_Click"/>

然后在你的button_click事件中,你可以像这样"捕捉"这个:

public void ShowButton_Click(object sender, EventArgs e)
{
  int ID = int.Parse(((Button)sender).CommandParameter.ToString());
}

编辑

若要使用此绑定,需要设置数据上下文。您可以在 ctor 中执行此操作,如下所示:

 public MainWindow()
    {
        InitializeComponent();
        // Adding some sample data for testing.
        tiles = new ObservableCollection<Tile>();
        tiles.Add(new Tile("Item 1"));
        tiles.Add(new Tile("Item 2"));
        // below You are setting a datacontext of a MainWindow to itself
        this.DataContext = this;
    }

另一个编辑

假设你的尾类有一个名为 ID 的属性。如果将此 ID 绑定到 Button.CommandParameter 稍后可以使用 linq 检索磁贴,如下所示:

public void ShowButton_click(object sender, EventArgs e)
{
   int MyId = int.Parse(((Button)sender).CommandParameter.ToString());
   Tile TileIWasSearchingFor = (from t in tiles where t.ID == MyId select t).First();
// do something with tile You found
}

好吧,由于我的要求相当"简单",我已经设法避免了命令。感谢MajkeloDev在这里的回答:https://stackoverflow.com/a/27419974/3998255 指导。

这是最后一个事件处理程序:

public void ShowButton_Click(object sender, EventArgs e)
    {
        Tile requestingTile = (sender as Button).DataContext as Tile;
        if(requestingTile != null)
            MessageBox.Show("Viewing item from: " + this.Data); 
            // Or whatever else you want to do with the object...
    }

此外,将 ItemSource 添加为 XAML 属性:

<ItemsControl x:Name="TileList" ItemsSource="{Binding tiles}">

并在 MainWindow 的构造函数中设置 DataContext:

public MainWindow()
{ 
    this.DataContext = this;
    // Whatever else you want to do...
}

好吧,它根据需要工作。