【问题标题】:Binding ObservableCollection in viewmodel to listbox将视图模型中的 ObservableCollection 绑定到列表框
【发布时间】:2015-05-18 21:21:36
【问题描述】:

我对 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>

【问题讨论】:

  • 如果您是 MVVM 新手,我强烈建议您考虑使用 MVVM 框架。一个例子(我使用的那个)是 Caliburn.Micro (caliburnmicro.com)。 MVVM 框架让事情变得超级简单,例如自动绑定到视图模型上的公共属性,只需在视图中设置控件的x:Name 以匹配属性名称。

标签: c# wpf mvvm binding viewmodel


【解决方案1】:

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

RaisePropertyChanged("_networkList1");

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

RaisePropertyChanged("NetworkList1");

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

【讨论】:

  • 感谢您查看我的问题,我尝试了您的建议,但不幸的是我仍然没有在列表框中获得任何数据。
  • 我刚刚注意到您还在代码和 XAML 中设置了 ItemSource 属性。在 MVVM 中,除了 DataContext 之外,您不必从代码中设置任何其他属性。一些框架甚至在 XAML 中做到这一点。
【解决方案2】:

除了 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;

        }
    }

应该让你的绑定工作。

*注意当你将DataContext设置为NetworkViewModel时,那么绑定在

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

有效,因为NetworkList1NetworkViewModel 的属性。

【讨论】:

    【解决方案3】:

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

    【讨论】:

    • 感谢您的洞察
    猜你喜欢
    • 2018-08-13
    • 2011-02-15
    • 2013-04-05
    • 2011-05-07
    • 2012-03-20
    • 2018-02-28
    • 2017-05-06
    • 1970-01-01
    相关资源
    最近更新 更多