应用。 ListView绑定到数据

时间:2016-02-25 13:37:23

标签: wpf listview data-binding

在我的应用程序中,我有一个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>

2 个答案:

答案 0 :(得分:0)

我怀疑这是你对EnumerateFiles的阻止。您正在UI线程上进行该调用。

在后台线程中执行大量处理时,您正在做正确的事情,但我也将EnumerateFiles移动到后台工作程序中。

答案 1 :(得分:0)

我发现了这个问题 这是嵌套ListView的ScrollViewer 我没有注意,它不是必需的,我猜它会给出无限的垂直长度,因此打破了默认情况下应该为ListView激活的虚拟化。
因此,只需删除ScrollViewer,即可快速完成绑定。