Reputation: 3509
I have an ObservableCollection and want to bind a Textbox to a specific element of that collection. The Items in the ObservableCollection are of a Type that implements INotifyPropertyChanged.
I have thought about creating a Property that selects the right element from the ObservableCollection, but then I would have to make this Property realise when the corresponding element in the Collection changes and I am not sure if this is the right way to do this.
Upvotes: 3
Views: 8780
Reputation: 3509
To solve my problem I created a Property that selects the right element from the ObservableCollection and created an event Handler that is added to the CollectionChanged event of the ObservableCollection and raises the PropertyChanged Event for my SelectionProperty.
In code that looks something like this in the constructor of the class containing the ObservableCollection and the SelectionProperty:
myObservableColleciton.CollectionChanged +=
new NotifyCollectionChangedEventHandler(
myObservableCollection_CollectionChanged);
somewhere else in the class define this event handler:
void myObservableCollection_CollectionChanged(
Object sender, NotifyCollectionChangedEventArgs e){
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("SelectionProperty"));
}
}
my selectionProperty looks something like this:
public User SelectionProperty
{
get { return myObservableCollection.First( user => user.id == 0); }
}
if the SelectionProperty depends on more than the ObservableCollection (maybe we want to find a user closest to a certain age, that is set elsewhere) then it needs to be made sure that the PropertyChanged event for SelectionProperty is raised as well, when those other properties change.
Upvotes: 3
Reputation: 43636
If the item you need is specific by index you can access using the index
<TextBlock Text="{Binding MyItemsSource[2]}" />
Upvotes: 5
Reputation: 4886
Usually, especially if you use MVVM, you'll have a viewModel with your ObservableCollection and a property for the SelectedItem that you update with data binding.
For example, your viewModel could look like this:
class ProductsViewModel : INotifyPropertyChanged
{
public ObservableCollection<Product> Products { get; set; }
private Product _selectedProduct;
public Product SelectedProduct
{
get { return _selectedProduct; }
set
{
_selectedProduct = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("SelectedProduct"));
}
}
public ProductsViewModel()
{
Products = new ObservableCollection<Product>();
Products.Add(new Product() { Name = "ProductA" });
Products.Add(new Product() { Name = "ProductB" });
}
public event PropertyChangedEventHandler PropertyChanged;
}
Your window object xaml:
<Window x:Class="ProductsExample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ListBox HorizontalAlignment="Left" Height="171" Margin="32,29,0,0" VerticalAlignment="Top" Width="176"
ItemsSource="{Binding Products}"
SelectedItem="{Binding SelectedProduct, Mode=TwoWay}"
DisplayMemberPath="Name"
/>
<TextBox HorizontalAlignment="Left" Height="33" Margin="36,226,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="172"
Text="{Binding SelectedProduct.Name, Mode=TwoWay}"/>
</Grid>
</Window>
and the code-behind where you just set the datacontext:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new ProductsViewModel();
}
}
Whenever you select a product in the listbox, the textbox is updated with the selected product, and if you change the product in the textbox (if product correctly implements INotifyPropertyChanged) the item in the listbox will also be updated.
Obviously you can achieve all this only using the code-behind, but for several reasons explained here: http://msdn.microsoft.com/en-us/magazine/dd419663.aspx, it is better to have a ViewModel
Upvotes: 5