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 的项目"。
那么推荐/有效的方法是什么呢?我的代码是否不适合此要求?
事件处理程序是错误的方法 - 使用Commands
,更重要的是MVVM。
正如我所看到的,你是新手(可能来自WinForms
或ASP.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...
}
好吧,它根据需要工作。