我有一个列表框,下面的代码是我要填充的900个项目。当我快速向下滚动列表时,出现“ ItemsControl与它的项目来源不一致”的异常。关于导致问题的原因有什么想法?
<ListBox x:Name="FileList" ItemsSource="{Binding Files}" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.CanContentScroll="True"
MaxHeight="520" >
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<CheckBox x:Name="FileChecked" IsChecked="{Binding Checked}" Grid.Column="0" BorderThickness="1"/>
<Label Content="{Binding Name}" Grid.Column="1" />
<Label Content="{Binding Source}" Grid.Column="2" Style="{StaticResource FileProperties}" />
<Label Content="{Binding Destination}" Grid.Column="3" Style="{StaticResource FileProperties}"/>
<Label Content="{Binding ArchiveLocation}" Grid.Column="4" Style="{StaticResource FileProperties}"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
以下是该问题的视频。 https://www.screencast.com/t/YUlp24zoXiG
答案 0 :(得分:0)
我相信我已经找到了问题。我在下面粘贴了有问题的代码,以便其他访问者可以从此答案中受益。
// Your code from GitHub unchanged
private async void Preview_Click(object sender, System.Windows.RoutedEventArgs e)
{
vm.Files = new List<InstrumentFile>();
try
{
for (int i = 0; i < InstrumentList.Items.Count; i++)
{
ListBoxItem lbi = (InstrumentList.ItemContainerGenerator.ContainerFromIndex(i)) as ListBoxItem;
ContentPresenter cp = GetFrameworkElementByName<ContentPresenter>(lbi);
DataTemplate dt = InstrumentList.ItemTemplate;
CheckBox cb = (dt.FindName("InstrumentChecked", cp)) as CheckBox;
if (cb.IsChecked == true)
{
List<InstrumentFile> instrumentFiles = new List<InstrumentFile>();
Instrument instrument = ((Instrument)(InstrumentList.Items[i]));
string[] files = Directory.GetFiles(instrument.FileSource);
foreach (string file in files)
{
FileInfo fi = new FileInfo(file);
instrumentFiles.Add(new InstrumentFile()
{
Name = fi.Name,
Source = instrument.FileSource,
Destination = instrument.Destination,
ArchiveLocation = instrument.ArchiveLocation
});
}
if (string.IsNullOrEmpty(instrument.FileExt) == false)
{
IEnumerable<InstrumentFile> filteredFiles = instrumentFiles.Where(f => f.Name.ToUpper().EndsWith(instrument.FileExt.ToUpper()));
if (filteredFiles.Count() > 0)
vm.Files.AddRange(filteredFiles);
}
else
{
if (instrumentFiles.Count > 0)
vm.Files.AddRange(instrumentFiles);
}
}
}
}
catch (Exception ex)
{
await metroWindow.ShowMessageAsync("Exception Encountered", ex.Message, MessageDialogStyle.Affirmative, Helpers.DialogSettings());
}
FileCount.Content = vm.Files.Count.ToString() + " files";
}
在这里,您正在初始化视图模型中的Files
属性。这将导致数据绑定更新为空列表。到目前为止没有问题。但是,您随后将内容添加到Files
,但是这些更改不会传播到数据绑定系统,因为视图模型中的列表不是ObservableCollection
。
您可以通过两种方法解决此问题。一种修复方法是在创建并填充列表后的 视图模型中设置Files
属性。新代码看起来像这样(缩写):
private async void Preview_Click(object sender, System.Windows.RoutedEventArgs e)
{
// Create new variable to store the list
var files = new List<InstrumentFile>();
// You do a bunch of things, but you now add items to files, not to vm.Files
files.AddRange(filteredFiles);
// Finally, change Files
vm.Files = files
}
最后一行将在视图模型中引发PropertyChanged
事件,以更新数据绑定,但会使用完整的项目列表进行此操作。
第二种解决方法是将视图模型中Files
的类型更改为ObservableCollection<InstrumentFile>
。每当您更改Files
时,都会引发正确的事件以更新数据绑定。