我有一个奇怪的绑定问题,我不明白:
我有一个名为VirtualizingCollection
的自创名单类型,它继承自IList
。它应绑定到ListView
。
我以三种不同的方式尝试。在某种程度上(我不喜欢它)它起作用,另外两种方式不起作用。
我在MVVM架构中实现了我的程序,因此我尝试使用viewmodel来显示它(参见方法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);
结果:未检测到输出中的绑定错误,但未显示数据。
Way3(不起作用)
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);
}
结果:未检测到输出中的绑定错误,但未显示数据。
答案 0 :(得分:0)
您的第一种方法确实有效,因为您在设置View的DataContext之前创建了test
。因此,当所有Bindings得到解决时,数据已经存在。
您的第3种方法不起作用,因为没有任何内容可以通知您查看您的财产test
的更改。如果要在ViewModel的构造函数中设置test
,您应该在View中看到一些数据。现在,没有任何内容可以触发关于test
属性的Binding更新。你可以这样做:
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
,以便在收藏集的内容发生变化时通知您的View。
答案 1 :(得分:0)
您的视图模型类应实现http://lists.typo3.org/pipermail/typo3-dev/2009-December/038130.html接口,并在设置getVisualBounds
属性时引发PropertyChanged
事件:
test
<强> XAML:强>
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));
}
}