1

バックグラウンド ワーカーを使用して、ロード アニメーションを表示しながら非常に大きなアイテム セットをロードします。ワーカーの実行完了イベントで、読み込まれたすべてのアイテムを監視可能なコレクションに設定し、読み込み画面をオフに切り替えます。問題は、アイテムが監視可能なコレクションに設定されるまで進行状況バーがスムーズにアニメーション化され、その後アニメーション化が停止することです。これは、これらのアイテムのレンダリングがアニメーションに干渉するためだと思います。レンダリング段階でアニメーションをスムーズにする方法はありますか? アプリケーションを実行すると、次の時間が得られます。

読み込み = 1000 ミリ秒
プロパティの設定 = 43 ミリ秒
レンダリング = 5083 ミリ秒

仮想化をオンにすると、レンダリングが 19 ミリ秒に向上します。長いレンダリング時間のシナリオを示すために、オフのままにします。

    public ObservableCollection<string> Items { get; set; }
    private IEnumerable<string> _items;
    private BackgroundWorker _worker;
    private long _loadTime;
    private long _renderTime;
    private long _setPropertiesTime;

    public MainWindow()
    {
        InitializeComponent();
        Items = new ObservableCollection<string>();
        _itemsGrid.DataContext = this;
        _worker = new BackgroundWorker();
        _worker.DoWork += DoWork;
        _worker.RunWorkerCompleted += RunWorkerCompleted;
    }

    private void Button_Click_1(object sender, RoutedEventArgs e)
    {
        _renderLabel.Content = string.Empty;
        _loadLabel.Content = string.Empty;
        _loadingBorder.Visibility = Visibility.Visible;
        _worker.RunWorkerAsync();            
    }

    void DoWork(object sender, DoWorkEventArgs e)
    {
        _items = LoadItems();            
    }

    void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        var setItemsTimer = Stopwatch.StartNew();
        Items.Clear();

        foreach (var item in _items)
        {
            Items.Add(item);
        }

        setItemsTimer.Stop();
        _setPropertiesTime = setItemsTimer.ElapsedMilliseconds;

        var timer = Stopwatch.StartNew();

        Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(() => 
        {
            timer.Stop();
            _loadLabel.Content = string.Format("Loading took {0} ms, Set properties took {1} ms", _loadTime, _setPropertiesTime);
            _renderLabel.Content = string.Format("Rendering took {0} ms", timer.ElapsedMilliseconds);
            _loadingBorder.Visibility = Visibility.Collapsed;
        }));
    }

    IEnumerable<string> LoadItems()
    {
        var timer = Stopwatch.StartNew();
        var items = new List<string>();
        for (int i = 0; i < 5000; i++)
        {
            items.Add("Testing");
        }

        Thread.Sleep(1000);

        timer.Stop();
        _loadTime = timer.ElapsedMilliseconds;
        return items;
    }
4

1 に答える 1

0

1 つの方法は、別の UI スレッドで実行されている現在の Window の上にオーバーレイ Window を作成し、この Window に読み込み中のアニメーションを表示し、適切なプロパティを設定して Window が読み込み中の Window の一部に見えるようにすることです。

これは本質的にスプラッシュ画面です。

于 2012-11-11T21:47:11.310 に答える