wpf 将视图模型中的 ObservableCollection 绑定到列表框

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30313003/
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 13:08:15  来源:igfitidea点击:

Binding ObservableCollection in viewmodel to listbox

c#wpfmvvmbindingviewmodel

提问by Phil

I'm very new to MVVM and bindings and I'm trying to learn to work with it. I run into the problem of binding my viewmodel to the view in particular binding an observable collection to a listbox.

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

this is what my viewmodel looks like:

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

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

in the view I have

在我看来

namespace MyProject
{
    public partial class Networking : Window
    {

        public Networking()
       {
            InitializeComponent();

            this.DataContext = new NetworkViewModel();

            lb1.ItemsSource = _networkList1;
        }
     }
}  

and in the XAML I have

在 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>

回答by Gaurav

It seems like you might have a typo in your view model.

看来您的视图模型中可能有错字。

RaisePropertyChanged("_networkList1");

You want to raise the property changed notification for the public property not the private variable.

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

RaisePropertyChanged("NetworkList1");

This might be preventing your view from updating properly.

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

回答by Bahman_Aries

In addition to Gaurav answer, if _networkList1is a private field in your NetworkViewModelclass, how is it possible to get access to it in Networkingwindow? I mean what's the meaning of the following line?

除了 Gaurav 的答案,如果_networkList1是您NetworkViewModel班级中的私有字段,如何在Networking窗口中访问它?我的意思是以下行的含义是什么?

lb1.ItemsSource = _networkList1;

when you define a Property(NetworkList1), you have to useit in order to get advantages of its features (e.g. to get RaisePropertyChangedworking). Otherwise what's the point, you could have just defined a field (_networklist1). So changing

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

_networkList1 = new ObservableCollection<Person>()

to

NetworkList1 = new ObservableCollection<Person>()

results in actually setting NetworkList1and therefore RaisePropertyChanged("NetworkList1")to be fired. (however if you want to just show data in a your listbox this is unnecessary)

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

and if i'm getting it right, changing this:

如果我做对了,请更改以下内容:

public partial class Networking : Window
{

    public Networking()
   {
        InitializeComponent();

        this.DataContext = new NetworkViewModel();

        lb1.ItemsSource = _networkList1;
    }
 }

to

    public partial class Networking : Window
    {

        public NetworkViewModel MyViewModel { get; set; }
        public Networking()
        {
            InitializeComponent();

            MyViewModel = new NetworkViewModel();

            this.DataContext = MyViewModel;

        }
    }

should get your binding to work.

应该让你的绑定工作。

*Note that when you set DataContextto NetworkViewModel, then the binding in

*请注意,当您设置DataContext为 时NetworkViewModel,则绑定

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

works, because NetworkList1is a Property of NetworkViewModel.

有效,因为NetworkList1是 的属性NetworkViewModel

回答by Oleksandr Zolotarov

Do not call RaisePropertyChanged()method on ObservableCollection<T>, for god's sake. This is a common mistake in a majority of cases (however, there are cases, where you need to reset ObservableCollection<T>using newkeyword, but they are kinda rare). This is a special type of collection which notifies UI internally about all the changes of its content (like add, remove etc.). What you need is to set the collection using newkeyword once in a lifetime of your ViewModel, and then manipulate your items via Add(T item), Remove(T item), Clear()methods etc. and UI will get notified about it and updated automatically.

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