我有一个奇怪的绑定问题,我不明白:
我有一个名为VirtualizingCollection
的自创建列表类型,它继承自IList
。它应与ListView
绑定。
我以三种不同的方式尝试。以一种方式(我不喜欢它(它有效,其他两种方式不起作用。
我在 MVVM 架构中实现了我的程序,所以我尝试使用视图模型来显示它(参见方式 3(。
方式1(有效(:
XAML 动态资源:
<Style x:Key="lvStyle" TargetType="{x:Type ListView}">
<Setter Property="ListView.ItemsSource" Value="{Binding}"/>
<Setter Property="ListView.View">
...
代码隐藏:
DataContext = new VirtualizingCollection<LinesSummary>(fs, 100);
结果: 数据显示在ListView
但 XAML 中所有其他绑定的DataContext
都消失了。所以这对我来说是没有选择的。
方式2(不起作用(
XAML 动态资源:
<Style x:Key="lvStyle" TargetType="{x:Type ListView}">
<Setter Property="ListView.ItemsSource" Value="{Binding test}"/>
<Setter Property="ListView.View">
...
代码隐藏:
VirtualizingCollection<LinesSummary> test = new VirtualizingCollection<LinesSummary>(fs, 100);
结果:未检测到输出中的绑定错误,但未显示数据。
方式3(不起作用(
XAML 动态资源
<Style x:Key="lvStyle" TargetType="{x:Type ListView}">
<Setter Property="ListView.ItemsSource" Value="{Binding test}"/>
<Setter Property="ListView.View">
...
代码隐藏:
myViewModel.x(fs)
视图模型:
public VirtualizingCollection<LinesSummary> test { get; set; }
public void x(FileSummarizer fs)
{
test = new VirtualizingCollection<LinesSummary>(fs, 100);
}
结果:在输出中未检测到绑定错误,但未显示数据。
第一种方法确实有效,因为您要在设置视图的数据上下文之前创建test
。因此,当解析所有绑定时,数据已经存在。
您的第三种方法不起作用,因为没有任何内容可以通知您的财产test
更改。如果要在视图模型的构造函数中设置test
,则应在视图中看到一些数据。目前,没有任何内容可以触发有关test
属性的绑定更新。你可以这样做:
public void x(FileSummarizer fs)
{
test = new VirtualizingCollection<LinesSummary>(fs, 100);
// Now you need to raise an event to notify the view.
// This line depends on if you are implementing INotifyPropertyChanged
// on your ViewModel directly or if you are yousing some ViewModel-Base
// class. Here's an example how it could look like:
RaisePropertyChanged("test");
}
另外:正如 Sasha 在评论中提到的,您的VirtualizingCollection
也应该实现某种INotifyPropertyChanged
以便在集合内容更改时收到通知。
视图模型类应实现 INotifyPropertyChanged 接口,并在设置test
属性时引发PropertyChanged
事件:
public class ViewModel : INotifyPropertyChanged
{
private VirtualizingCollection<LinesSummary> _test;
public VirtualizingCollection<LinesSummary> test
{
get { return _test; }
set { _test = value; OnPropertyChanged("test"); }
}
public void x(FileSummarizer fs)
{
//set the property, not the field:
test = new VirtualizingCollection<LinesSummary>(fs, 100);
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
XAML:
<Setter Property="ListView.ItemsSource" Value="{Binding test}"/>