Как сохранить работоспособность пользовательского интерфейса во время загрузки коллекции Observable? - PullRequest
0 голосов
/ 12 июля 2011

У меня синфузионный тайл, как показано ниже.

http://i.stack.imgur.com/JkrRS.jpg

Шаблон максимизированного элемента для этих элементов - TreeView. Источник древовидных объектов связан с Наблюдаемой коллекцией. Когда я максимизирую один из этих элементов, он загрузит данные из ViewModel, как показано ниже. Это в событии MaximizedItemChanged.

private void tileViewControl_Exchanges_MaximizedItemChanged(object sender, TileViewEventArgs args)
{
    if (args.Source != null)
    {
        TileViewControl tileViewControl = (TileViewControl)sender;
        TileViewItem tvi = (TileViewItem)args.Source;

        PanelViewModel panelViewModel = (PanelViewModel)tileViewControl.ItemContainerGenerator.ItemFromContainer(tvi);

        String currentSelectedPanelID = GetSelectedPanelID(tileViewControl);

        // below function will load all the treeview items. 
        SetSelectedExchangeID(tileViewControl, exchangePanelViewModel.ExchangeID);
    }
}

Но в дереве есть более тысячи предметов. Поэтому после нажатия на кнопку «Развернуть», это займет некоторое время, и программа зависнет. Есть ли способ плавного максимизации элемента и загрузки элемента Treeview на заднем плане? Что я хотел бы сделать, так это показать анимацию загрузки во время загрузки дерева, но теперь, когда оно развернулось (после зависания в течение 8 или 9 секунд), дерево уже загружено.

Редактировать: я добавил код для SetSelectedExchangeID.

public static readonly DependencyProperty SelectedExchangeIDProperty =
    DependencyProperty.RegisterAttached("SelectedExchangeID",
    typeof(String),
    typeof(UC_Contract_List),
    new UIPropertyMetadata(new PropertyChangedCallback(SelectedExchangeIDPropertyChanged)));

static void SelectedExchangeIDPropertyChanged(
    DependencyObject depObj,
    DependencyPropertyChangedEventArgs eventArgs)
{
    TileViewControl tileViewControl = (TileViewControl)depObj;
    ItemContainerGenerator itemContainerGenerator = tileViewControl.ItemContainerGenerator;
    String newPanelID = (String)eventArgs.NewValue;

    if (newPanelID != null)
    {
        if (tileViewControl.Visibility == Visibility.Visible)
        {
            foreach (PanelViewModel exchangePanel in tileViewControl.Items)
            {
                if (exchangePanel.ExchangeID.Equals(newExchangeID))
                {
                    TileViewItem tvi = (TileViewItem)itemContainerGenerator.ContainerFromItem(exchangePanel);
                    try
                    {
                        if (tileViewControl.tileViewItems != null)
                        {
                            if (tvi.TileViewItemState != TileViewItemState.Maximized)
                            {
                                tvi.TileViewItemState = TileViewItemState.Maximized;
                            }
                        }
                    }
                    catch (Exception e) { }
                    break;
                }
            }
        } 
    }
    else
    {
        foreach (PanelViewModel exchangePanel in tileViewControl.Items)
        {
            TileViewItem tvi = (TileViewItem)itemContainerGenerator.ContainerFromItem(exchangePanel);
            tvi.TileViewItemState = TileViewItemState.Normal;
        }
    }
}

public static void SetSelectedExchangeID(DependencyObject depObj, String exchangeID)
{
    depObj.SetValue(SelectedExchangeIDProperty, exchangeID);
}

public static String GetSelectedExchangeID(DependencyObject depObj)
{
    return (String)depObj.GetValue(SelectedExchangeIDProperty);
}    

А в ViewModel:

String _selectedExchangeID;        
public String SelectedExchangeID
{
    get { return this._selectedExchangeID; }
    set
    {
        if (value == null)
        {
            this.ClearPanels();
            this._selectedExchangeID = value;
        }
        else
        {
            this._selectedExchangeID = value;
            PanelViewModel curPanelViewModel = this.GetPanelViewModel(this._selectedExchangeID);
            if (curPanelViewModel != null)
            {
                curPanelViewModel.Activate(); // this will add to the observable collection for Treeview ItemsSource
            }
        } 
        this.OnPropertyChanged("SelectedExchangeID");
    }
}

Ответы [ 2 ]

1 голос
/ 12 июля 2011

Это можно сделать, выполнив асинхронную задачу обработки / тяжелой загрузки в фоновом потоке и синхронизировав с основным потоком с помощью объекта UI Dispatcher, только когда все доступно и обработано.

Подробнее о BackgroundWorker см. MSDN .

Обратите внимание, что BackgroundWorker - не единственный способ выполнить асинхронную задачу. Вы можете выбрать Задачи (представленные в .net 4.0) или BeginInvoke / EndInvoke.

И когда вы закончите с тяжелым заданием, вы можете выполнить синхронизацию с потоком переднего плана следующим образом. Сначала инициализируйте диспетчер в потоке пользовательского интерфейса (скажем, Конструктор представлений):

Dispatcher _UIDispatcher;

public MyView 
{
  ...
  _UIDispatcher = Dispatcher.CurrentDispatcher;
}

Затем выполнить синхронизацию после завершения загрузки:

public void SyncPostLoading(IEnumerable<Something> myData)
{
     _UIDispatcher.BeginInvoke(DispatcherPriority.ContextIdle,  System.Threading.ThreadStart)delegate()
     {
          foreach(Something something in myData)
           myObervableCollection.Add(something);   
      });
}
0 голосов
/ 12 июля 2011

У вас есть несколько различных вариантов работы в фоновом потоке.Вы можете использовать фонового работника (немного устаревшего) или задачи .NET 4.0 (часть параллельной библиотеки задач).Вам необходимо решить, хотите ли вы загрузить все данные в новую коллекцию и вызвать обновление для потока GUI одновременно, или же вы хотите загружать элементы в пакетах и ​​вызывать эти пакеты в GUI в несколько раундов

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...