0

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

客观的

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

现在,我想绑定 Button 的“Click”事件,以便调用 Tile 类中定义的 Event Handler 方法。

换句话说,当我单击 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”。

那么推荐/有效的方法是什么?我的代码不适合这个要求吗?

4

3 回答 3

2

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

正如我所看到的,您是新手(可能来自某个WinFormsASP.NET背景),您应该阅读此博客以了解您的想法需要如何改变 - 这是在解决之前要了解的最重要部分WPFhttp ://rachel53461.wordpress.com /2012/10/12/从-winforms-切换到-wpfmvvm/

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

于 2014-12-11T09:43:17.887 回答
1

让我从一些基础知识开始:不要在 codeBehind 中分配 itemsource - 像这样使用 Binding:

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

有很多方法可以实现这一目标。我认为使用 this.Data 并不是最好的解决方案。例如,如果您的尾巴有 ID 或其他东西,您可以将此 ID 分配给按钮 CommandParameter,如下所示

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

编辑

要使用此绑定,您需要设置 DataContext。您可以像这样在 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
}
于 2014-12-11T09:59:59.697 回答
1

好吧,因为我的要求相当“简单”,所以我设法解决了问题,避免了命令。感谢 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...
}

好吧,它按要求工作。

于 2014-12-13T16:04:01.863 回答