wpf 如何绑定到 ObservableCollection 的一个元素

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18498898/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 09:31:59  来源:igfitidea点击:

How to bind to one element of an ObservableCollection

c#wpfdata-binding

提问by FlyingFoX

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.

我有一个 ObservableCollection 并且想要将一个文本框绑定到该集合的特定元素。ObservableCollection 中的项目属于实现 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.

我曾想过创建一个从 ObservableCollection 中选择正确元素的属性,但是当集合中的相应元素发生更改时,我必须使这个属性实现,我不确定这是否是正确的方法。

回答by Rui

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.

通常,特别是如果您使用 MVVM,您将拥有一个带有 ObservableCollection 的 viewModel 和您使用数据绑定更新的 SelectedItem 的属性。

For example, your viewModel could look like this:

例如,您的 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;
}

Your window object xaml:

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

每当您在列表框中选择产品时,文本框都会更新为所选产品,如果您更改文本框中的产品(如果产品正确实现 INotifyPropertyChanged),列表框中的项目也将更新。

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

显然,您只能使用代码隐藏来实现这一切,但由于这里解释的几个原因:http: //msdn.microsoft.com/en-us/magazine/dd419663.aspx,最好有一个 ViewModel

回答by sa_ddam213

If the item you need is specific by index you can access using the index

如果您需要的项目特定于索引,您可以使用索引访问

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

回答by FlyingFoX

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.

为了解决我的问题,我创建了一个属性,该属性从 ObservableCollection 中选择了正确的元素,并创建了一个事件处理程序,该事件处理程序添加到 ObservableCollection 的 CollectionChanged 事件中,并为我的 SelectionProperty 引发 PropertyChanged 事件。

In code that looks something like this in the constructor of the class containing the ObservableCollection and the SelectionProperty:

在包含 ObservableCollection 和 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:

我的 selectionProperty 看起来像这样:

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.

如果 SelectionProperty 依赖的不仅仅是 ObservableCollection(也许我们想找到一个最接近某个年龄的用户,这是在别处设置的)那么需要确保也引发了 SelectionProperty 的 PropertyChanged 事件,当那些其他属性改变。