【问题标题】:Getting clicked Item object using XAML databinding使用 XAML 数据绑定获取单击的 Item 对象
【发布时间】:2017-03-08 23:31:39
【问题描述】:

我将我的 ListBox 绑定到一个项目集合,其中包含我的项目类的实例。

这部分按预期工作。我遇到的问题是访问单击的列表框项目item 实例。我已经包含了完整的示例和相关的 XAML。

我还提供了一个示例,说明我希望如何访问 listBoxItems_PreviewMouseDown 事件处理程序中的 Item 实例。

我认为我遗漏了一些明显的东西,但是当我单击一个项目时代码会崩溃。我是否缺少将所有这些粘合在一起的另一个绑定?

谢谢

背后的代码

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Threading;

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        // Item class
        internal class Item : INotifyPropertyChanged
        {
            public Item(string name = null)
            {
                this.Name = name;
            }

            public string Name { get; set; }
            public string ImagePath { get; set; }
            public string SomeString { get; set; }
            public int SomeInt { get; set; }

            public event PropertyChangedEventHandler PropertyChanged;
            private void NotifyPropertyChanged(String propertyName)
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                }
            }
        }

        // Item collection
        ObservableCollection<Item> ItemsCollection;

        public MainWindow()
        {
            InitializeComponent();

            // Initialize the items collection
            this.ItemsCollection = new ObservableCollection<Item>();

            for (int i = 0; i < 5; i ++)
            {
                Dispatcher.Invoke(new Action(() =>
                {
                    Item newItem = new Item
                    {
                        Name = "test " + i,
                        ImagePath = @"Images\" + i + ".jpg",
                        SomeString = "example" + i,
                        SomeInt = i,
                    };

                    // Add the new item to the collection
                    this.ItemsCollection.Add(newItem);
                }), DispatcherPriority.Background);
            }

            // Set the items source
            this.listBoxItems.ItemsSource = this.ItemsCollection;
        }

        // Handle mouse down events on listbox items
        private void listBoxItems_PreviewMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            // Ideally, i'd like to do something like this
            Item item = sender as Item;

            // So then I could do for example
            Console.WriteLine(@"Clicked item SomeString: {0}, SomeInt {1}", item.SomeString, item.SomeInt);
        }
    }
}

XAML

<userControls:MyListBox x:Name="ItemsListBox" ItemsSource="{Binding ItemsCollection}" PreviewMouseDown="listBoxItems_PreviewMouseDown">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <VirtualizingStackPanel>
                <Image Source="{Binding ImagePath}" Width="200" Height="100"/>
                <TextBlock Text="{Binding Name}" />
            </VirtualizingStackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</userControls:MyListBox>

【问题讨论】:

  • 在您的情况下,发件人将是列表,因此将发件人转换为列表。取出其选定的项目。将其转换为 ListItem 并将其 DataContext 转换为 Item 类型。
  • @NikhilAgrawal 如果我将发件人投射到 List 我如何检索所选项目?
  • 我的错。 sender 将是 ListBox,因此将 sender 转换为 ListBox。取出其选定的项目。将其转换为 ListItem 并将其 DataContext 转换为 Item 类型。
  • @NikhilAgrawal 所以你的意思是这样的? gist.github.com/DannyGlover/bbf2bf5900510445abf12e8a55854cd8 - 它仍然崩溃,所以也许我对你的解释不正确。感谢您迄今为止的帮助。

标签: c# wpf xaml listbox click


【解决方案1】:

除了接受的答案之外,您还可以将PreviewMouseDown 事件直接绑定到ListBoxItem

在这种情况下,XAML 可以是(强调添加的&lt;ListBox.ItemContainerStyle&gt; 节点):

<userControls:MyListBox x:Name="ItemsListBox" ItemsSource="{Binding ItemsCollection}" PreviewMouseDown="listBoxItems_PreviewMouseDown">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <VirtualizingStackPanel>
                <Image Source="{Binding ImagePath}" Width="200" Height="100"/>
                <TextBlock Text="{Binding Name}" />
            </VirtualizingStackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
    <ListBox.ItemContainerStyle>
        <Style TargetType="{x:Type ListBoxItem}">
            <EventSetter Event="PreviewMouseDown" Handler="listBoxItems_PreviewMouseDown" />
        </Style>
    </ListBox.ItemContainerStyle>
</userControls:MyListBox>

以及处理程序

    // Handle mouse down events on listbox items
    private void listBoxItems_PreviewMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {

        // Ideally, i'd like to do something like this
        Item item = (sender as ListBoxItem).DataContext as Item;

        // So then I could do for example
        Console.WriteLine(@"Clicked item SomeString: {0}, SomeInt {1}", item.SomeString, item.SomeInt);
    }

【讨论】:

  • 这个答案甚至比前一个更好,因为它导致后面的代码更干净(恕我直言)。非常感谢!
【解决方案2】:

您可以获取该事件的OriginalSource 并检查其DataContext

var item = (e.OriginalSource as FrameworkElement)?.DataContext as Item;
if (item != null) { /* Do something with item... */ }

【讨论】:

  • 效果很好!现在更有意义(问题和解决方案)。非常感谢。
猜你喜欢
  • 2013-01-25
  • 1970-01-01
  • 1970-01-01
  • 2013-05-03
  • 2011-04-05
  • 1970-01-01
  • 2010-11-14
  • 2011-07-20
  • 1970-01-01
相关资源
最近更新 更多