将viewmodel中的ObservableCollection绑定到listbox

本文关键字:listbox 绑定 ObservableCollection viewmodel 中的 | 更新日期: 2023-09-27 17:49:41

我对MVVM和绑定很陌生,我正在努力学习使用它。我遇到了将视图模型绑定到视图的问题,特别是将一个可观察集合绑定到一个列表框。

这是我的视图模型的样子:

namespace MyProject
{
    using Model; 
public class NetworkViewModel: INotifyPropertyChanged
{
    private ObservableCollection<Person> _networkList1 = new ObservableCollection<Person>();
    public ObservableCollection<Person> NetworkList1 //Binds with the listbox
    {
        get { return _networkList1; }
        set { _networkList1 = value; RaisePropertyChanged("_networkList1"); }
    }
    public event PropertyChangedEventHandler PropertyChanged;
    private void RaisePropertyChanged(string propertyName)
    {
        var handler = this.PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    public NetworkViewModel() 
    {
        _networkList1 = new ObservableCollection<Person>()
        {
            new Person(){FirstName="John", LastName="Doe"},
            new Person(){FirstName="Andy" , LastName="Boo"}
        };
   }
}

在视图中我有

namespace MyProject
{
    public partial class Networking : Window
    {
        public Networking()
       {
            InitializeComponent();
            this.DataContext = new NetworkViewModel();
            lb1.ItemsSource = _networkList1;
        }
     }
}  

在XAML中我有

<ListBox x:Name="lb1" HorizontalAlignment="Left" ItemsSource="{Binding NetworkList1}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <TextBlock >
                         <Run Text="{Binding Path=FirstName}"/>
                         <Run Text="{Binding Path=LastName}"/>
                    </TextBlock>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

将viewmodel中的ObservableCollection绑定到listbox

似乎你的视图模型中有一个错别字。

RaisePropertyChanged("_networkList1");

您希望为公共属性而不是私有变量引发属性更改通知。

RaisePropertyChanged("NetworkList1");

这可能会阻止你的视图正确更新

除了Gaurav答案,如果_networkList1是您的NetworkViewModel类中的私有字段,如何能够在Networking窗口中访问它?我的意思是,下面这行是什么意思?

lb1.ItemsSource = _networkList1;

当您定义属性 (NetworkList1)时,您必须使用它以获得其功能的优势(例如使RaisePropertyChanged工作)。否则有什么意义呢,您可以只定义一个字段(_networklist1)。所以改变

_networkList1 = new ObservableCollection<Person>()

NetworkList1 = new ObservableCollection<Person>()

导致实际设置NetworkList1,因此触发RaisePropertyChanged("NetworkList1")。(但是如果你只想在列表框中显示数据,这是不必要的)

如果我写对了,改一下:

public partial class Networking : Window
{
    public Networking()
   {
        InitializeComponent();
        this.DataContext = new NetworkViewModel();
        lb1.ItemsSource = _networkList1;
    }
 }

    public partial class Networking : Window
    {
        public NetworkViewModel MyViewModel { get; set; }
        public Networking()
        {
            InitializeComponent();
            MyViewModel = new NetworkViewModel();
            this.DataContext = MyViewModel;
        }
    }

应该使你的绑定工作。

*注意当你设置DataContextNetworkViewModel时,那么

中的绑定
<ListBox x:Name="lb1" HorizontalAlignment="Left" ItemsSource="{Binding NetworkList1}">

可以工作,因为NetworkList1NetworkViewModel的属性

看在上帝的份上,不要在ObservableCollection<T>上调用RaisePropertyChanged()方法。在大多数情况下,这是一个常见的错误(然而,在某些情况下,您需要使用new关键字重置ObservableCollection<T>,但它们有点罕见)。这是一种特殊类型的集合,它在内部通知UI有关其内容的所有更改(如添加,删除等)。您需要的是在ViewModel的生命周期中使用new关键字设置一次集合,然后通过Add(T item), Remove(T item), Clear()方法等操作您的项目。UI会收到通知并自动更新