在我的应用程序中,我有一个ListView绑定到'XMLFileModel'列表,请参阅下面的代码。
当我用340个项目填充此列表时,可以看到没有延迟
当我使用5640项目填充此列表时,该应用程序。冻结约15秒
当我用12080个项目填充此列表时,应用程序。冻结约50秒
所以我有两个问题:
1)这些延误是否也会导致你常见的延误?
2)我将代码放在BackgroundWorker中,但应用程序仍然冻结。为什么?
我可以忍受延迟,我有一个进度条向用户显示处理但问题是进度条填充到100%然后非常快速地隐藏(少于1秒)然后应用程序。使用ListView清空冻结。 所以似乎延迟来自数据绑定处理。
以下是启动数据加载的命令的代码:
private void OnSelectRootFolderCommand()
{
var dialog = new FolderBrowserDialog();
dialog.Description = "Select the XML files folder";
var dialogResult = dialog.ShowDialog();
if (dialogResult == DialogResult.OK)
{
RootFolder = dialog.SelectedPath;
var files = Directory.EnumerateFiles(RootFolder, "*.xml",
IsSubfolders ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly)
.Where(f => Path.GetExtension(f) == ".xml");
ProgressBarVisibility = Visibility.Visible;
progressBarWorker.RunWorkerAsync(files);
}
}
以下是'XMLFileModel'的代码:
public class XMLFileModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public string Name { get; set; }
public DateTime LastWriteTime { get; set; }
private string status;
public string Status
{
get { return status; }
set
{
if (status != value)
{
status = value;
OnPropertyChanged();
}
}
}
private bool isSelected;
public bool IsSelected
{
get { return isSelected; }
set
{
if (isSelected != value)
{
isSelected = value;
OnPropertyChanged();
}
}
}
private void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
以下是绑定数据的BackgroundWorker RunWorkerAsync运行的方法的代码:
private void ProgressBarWorkerDoWork(object sender, DoWorkEventArgs e)
{
var filesList = new List<XMLFileModel>();
try
{
var xmlFiles = e.Argument as IEnumerable<string>;
if (xmlFiles != null && xmlFiles.Any())
{
var xmlFilesList = xmlFiles.ToArray();
var filesCount = xmlFilesList.Count();
int percentageDone = 0;
for (int i = 0; i < filesCount; i++)
{
var xmlFile = xmlFilesList[i];
var fileModel = new XMLFileModel
{
Name = xmlFile,
Status = ParseResultEnum.NotProcessed.ToString(),
LastWriteTime = File.GetLastWriteTime(xmlFile),
IsSelected = true
};
filesList.Add(fileModel);
percentageDone = (int)(((i + 1.0d) / (double)filesCount) * 100.0d);
progressBarWorker.ReportProgress(percentageDone);
}
}
XMLFiles = filesList;
}
catch (Exception ex)
{
Services.Instance.Logger.Error(ex);
System.Windows.Application.Current.Dispatcher.Invoke(() =>
messageBoxService.ShowError(ex.Message));
}
}
当上述方法'ProgressBarWorkerDoWork'完全执行时,延迟开始。
以下是视图的XAML代码:
<Border DockPanel.Dock="Top" BorderThickness="1" BorderBrush="Black" Margin="1">
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<ListView Margin="2" ItemsSource="{Binding XMLFiles, Mode=OneWay}" SelectedItem="{Binding SelectedItem}"
dragdrop:DragDropHelper.IsDragSource="True" dragdrop:DragDropHelper.IsDropTarget="True">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="IsSelected" Value="{Binding Mode=TwoWay, Path=IsSelected}" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Status}" Value="Error">
<Setter Property="Background" Value="Red" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=Status}" Value="Processed">
<Setter Property="Background" Value="LimeGreen" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=Status}" Value="Invalid">
<Setter Property="Background" Value="Red" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=Status}" Value="Ignored">
<Setter Property="Background" Value="Orange" />
</DataTrigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
<ListView.View>
<GridView>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding Path=IsSelected, RelativeSource={RelativeSource AncestorType={x:Type ListViewItem}}}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Name" Width="700" DisplayMemberBinding="{Binding Name}" />
<GridViewColumn Header="DateTime" Width="144" DisplayMemberBinding="{Binding LastWriteTime}" />
<GridViewColumn Header="Status" Width="88" DisplayMemberBinding="{Binding Status}" />
</GridView>
</ListView.View>
</ListView>
</ScrollViewer>
</Border>
答案 0 :(得分:0)
我怀疑这是你对EnumerateFiles
的阻止。您正在UI线程上进行该调用。
在后台线程中执行大量处理时,您正在做正确的事情,但我也将EnumerateFiles
移动到后台工作程序中。
答案 1 :(得分:0)
我发现了这个问题
这是嵌套ListView的ScrollViewer
我没有注意,它不是必需的,我猜它会给出无限的垂直长度,因此打破了默认情况下应该为ListView激活的虚拟化。
因此,只需删除ScrollViewer,即可快速完成绑定。