如何绑定到ObservableCollection的一个元素

3
我有一个 ObservableCollection,并且想要将一个 Textbox 绑定到该集合中的特定元素。ObservableCollection 中的项是实现了 INotifyPropertyChanged 接口的类型。
我考虑创建一个 Property,选取 ObservableCollection 中正确的元素,但是我不确定这是否是正确的方法,因为这个 Property 还需要意识到集合中相应元素的变化。

按索引还是属性值进行特定的操作? - sa_ddam213
按元素的属性值进行特定筛选,而不是按索引。 - FlyingFoX
3个回答

5

通常情况下,尤其是如果您使用MVVM,您会拥有一个包含ObservableCollection和用于通过数据绑定更新的SelectedItem属性的viewModel。

例如,您的viewModel可能如下所示:

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

您的窗口对象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>

还有代码后台,你只需设置数据上下文:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = new ProductsViewModel();
    }
}

每当您在列表框中选择一个产品时,文本框将更新为所选产品。如果您更改文本框中的产品(如果产品正确实现了INotifyPropertyChanged),则列表框中的项目也将被更新。
显然,您只能使用代码后端来实现所有这些功能,但出于多种原因,最好拥有ViewModel,详细解释请参见此处:http://msdn.microsoft.com/en-us/magazine/dd419663.aspx

5

如果您需要访问特定索引的项目,则可以使用该索引进行访问。

 <TextBlock Text="{Binding MyItemsSource[2]}" />

3
为了解决我的问题,我创建了一个属性,从ObservableCollection中选择正确的元素,并创建了一个事件处理程序,将其添加到ObservableCollection的CollectionChanged事件中,并为我的SelectionProperty引发PropertyChanged事件。
在包含ObservableCollection和SelectionProperty的类的构造函数中,代码看起来像这样:
myObservableColleciton.CollectionChanged += 
        new NotifyCollectionChangedEventHandler(
        myObservableCollection_CollectionChanged);

在类的其他地方定义此事件处理程序:

void myObservableCollection_CollectionChanged(
        Object sender, NotifyCollectionChangedEventArgs e){
   if (PropertyChanged != null)
   {
       PropertyChanged(this, new PropertyChangedEventArgs("SelectionProperty"));
   }
}

我的selectionProperty大致如下:

public User SelectionProperty
{
     get { return myObservableCollection.First( user => user.id == 0); }
}

如果SelectionProperty依赖于不止ObservableCollection(也许我们想要找到一个年龄最接近某个特定年龄的用户,该年龄在其他地方设置),那么当这些其他属性发生变化时,必须确保为SelectionProperty引发PropertyChanged事件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接