2017-03-08 83 views
1

我将我的ListBox绑定到包含我物品类的实例的物品集合。使用XAML数据绑定获取单击的物品对象

该零件按预期工作。我遇到的问题是访问点击列表框项目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> 
+0

你的情况,发件人将是List,所以将发件人转换为列表。拿出其选定的项目。将其转换为ListItem并将其'DataContext'强制转换为'Item'类型。 –

+0

@NikhilAgrawal如果我将发件人发送到列表如何检索所选项目? – PersuitOfPerfection

+0

我的不好。 'sender'将是'ListBox',所以将发送者转换为ListBox。拿出其选定的项目。将其转换为'ListItem'并将其'DataContext'转换为'Item'类型。 –

回答

1

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

在这种情况下,XAML可以(重点增加<ListBox.ItemContainerStyle>节点上):

<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); 
    } 
+0

这个答案比前一个更好,因为它会导致更清晰(imho)的代码。非常感谢你! – PersuitOfPerfection

1

你可以得到事件的OriginalSource并检查其DataContext

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

完美的工作!使现在更有意义(问题和解决方案)。非常感谢你。 – PersuitOfPerfection