将视图模型中的 ObservableCollection 绑定到列表框
Binding ObservableCollection in viewmodel to listbox
我对 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>
您的视图模型中似乎有错字。
RaisePropertyChanged("_networkList1");
您想为 public 属性 而非私有变量发出 属性 更改通知。
RaisePropertyChanged("NetworkList1");
这可能会阻止您的视图正确更新。
除了 Gaurav 回答之外,如果 _networkList1
是您 NetworkViewModel
class 中的私有字段,如何在 Networking
中访问它 window?我的意思是下面这行是什么意思?
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}">
有效,因为 NetworkList1
是 NetworkViewModel
的 属性。
不要在 ObservableCollection<T>
上调用 RaisePropertyChanged()
方法,看在上帝的份上。这是大多数情况下的常见错误(但是,在某些情况下,您需要使用 new
关键字重置 ObservableCollection<T>
,但这种情况很少见)。
这是一种特殊类型的集合,它在内部通知 UI 其内容的所有更改(如添加、删除等)。您需要在 ViewModel 的生命周期中使用 new
关键字设置一次集合,然后通过 Add(T item)
、Remove(T item)
、Clear()
方法等操作您的项目。
UI 会收到通知并自动更新。
我对 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>
您的视图模型中似乎有错字。
RaisePropertyChanged("_networkList1");
您想为 public 属性 而非私有变量发出 属性 更改通知。
RaisePropertyChanged("NetworkList1");
这可能会阻止您的视图正确更新。
除了 Gaurav 回答之外,如果 _networkList1
是您 NetworkViewModel
class 中的私有字段,如何在 Networking
中访问它 window?我的意思是下面这行是什么意思?
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}">
有效,因为 NetworkList1
是 NetworkViewModel
的 属性。
不要在 ObservableCollection<T>
上调用 RaisePropertyChanged()
方法,看在上帝的份上。这是大多数情况下的常见错误(但是,在某些情况下,您需要使用 new
关键字重置 ObservableCollection<T>
,但这种情况很少见)。
这是一种特殊类型的集合,它在内部通知 UI 其内容的所有更改(如添加、删除等)。您需要在 ViewModel 的生命周期中使用 new
关键字设置一次集合,然后通过 Add(T item)
、Remove(T item)
、Clear()
方法等操作您的项目。
UI 会收到通知并自动更新。