2017-03-08 57 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