protected void UpdatePreparedItems() { bool doSetItems; bool doSetChildren; ItemCollection preparedItems; ItemCollection preparedChildren; lock (_renderLock) { if (!_setItems && !_setChildren) { return; } doSetItems = _setItems; _setItems = false; doSetChildren = _setChildren; _setChildren = false; preparedItems = _preparedItems; _preparedItems = null; preparedChildren = _preparedChildren; _preparedChildren = null; } Panel itemsHostPanel = _itemsHostPanel; if (doSetChildren) { FrameworkElementCollection children = itemsHostPanel.Children; lock (children.SyncRoot) { children.Clear(false); if (preparedChildren != null) { IList <FrameworkElement> tempItems = new List <FrameworkElement>(preparedChildren.Count); foreach (object item in preparedChildren.ExtractElements()) { FrameworkElement fe = item as FrameworkElement; if (fe == null) { MPF.TryCleanupAndDispose(item); continue; } ISelectableItemContainer sic = item as ISelectableItemContainer; if (sic != null && sic.Selected) { _lastSelectedItem = sic; } tempItems.Add(fe); } children.AddAll(tempItems); preparedChildren.Dispose(); } } } if (doSetItems) { _items.Clear(); if (preparedItems != null) { _items.AddAll(preparedItems.ExtractElements()); preparedItems.Dispose(); } } var vsp = itemsHostPanel as IVirtualizingPanel; if (vsp == null) { IsEmpty = itemsHostPanel.Children.Count == 0; } // else IsEmpty has been updated by PrepareItemsOverride }
protected virtual void PrepareItemsOverride(bool force) { if (_panelTemplateApplied && _itemsHostPanel != null && !force) { return; } // Check properties which are necessary in each case if (ItemsPanel == null) { return; } ItemsPresenter presenter = FindItemsPresenter(); if (presenter == null) { return; } if (!_panelTemplateApplied) { _panelTemplateApplied = true; presenter.ApplyTemplate(ItemsPanel); _itemsHostPanel = null; } if (_itemsHostPanel == null) { _itemsHostPanel = presenter.ItemsHostPanel; } if (_itemsHostPanel == null) { return; } // Albert: We cannot exit the method if one of the styles is not set because the styles // might be found by the SkinEngine's automatic Style assignment (FrameworkElement.CopyDefaultStyle) //if (ItemContainerStyle == null || ItemTemplate == null) // return; IEnumerable itemsSource = ItemsSource; if (itemsSource == null) { // In this case, we must set up the items control using the Items property ItemCollection items = _items; ItemCollection preparedChildren = new ItemCollection(); bool setItems = false; if (items == null) { // Restore items from "ItemsSource mode" where they have been set to null items = new ItemCollection(); setItems = true; } foreach (object item in items) { object itemCopy = MpfCopyManager.DeepCopyWithFixedObject(item, this); // Keep this object as LogicalParent FrameworkElement element = itemCopy as FrameworkElement ?? PrepareItemContainer(itemCopy); if (element.Style == null && element is ContentControl) { element.Style = ItemContainerStyle; } element.LogicalParent = this; preparedChildren.Add(element); } presenter.SetDataStrings(BuildDataStrings(items)); SetPreparedItems(setItems, setItems ? items : null, true, preparedChildren); } else { IList <object> l = new List <object>(); ISynchronizable sync = itemsSource as ISynchronizable; if (sync != null) { lock (sync.SyncRoot) CollectionUtils.AddAll(l, itemsSource); } else { CollectionUtils.AddAll(l, itemsSource); } presenter.SetDataStrings(BuildDataStrings(l)); var vsp = _itemsHostPanel as IVirtualizingPanel; if (vsp != null) { // In this case, the VSP will generate its items by itself ListViewItemGenerator lvig = new ListViewItemGenerator(); lvig.Initialize(this, l, ItemContainerStyle, ItemTemplate); SimplePropertyDataDescriptor dd; if (SimplePropertyDataDescriptor.CreateSimplePropertyDataDescriptor(this, "IsEmpty", out dd)) { SetValueInRenderThread(dd, l.Count == 0); } vsp.SetItemProvider(lvig); SetPreparedItems(true, null, false, null); } else { ItemCollection preparedItems = new ItemCollection(); preparedItems.AddAll(l.Select(PrepareItemContainer)); SetPreparedItems(true, null, true, preparedItems); } } }
/// <summary> /// Called after the collection of items to be displayed has been set up. /// </summary> /// <param name="setItems">If set to <c>true</c>, the <see cref="Items"/> will be set to the given <paramref name="preparedItems"/>, /// else, the <see cref="Items"/> will be left unchanged.</param> /// <param name="preparedItems">Elements to be put into the <see cref="Items"/> collection.</param> /// <param name="setChildren">If set to <c>true</c>, the children of our host panel will be set to the given /// <paramref name="preparedChildren"/>, else, they will be left unchanged.</param> /// <param name="preparedChildren">Elements to be put into the <see cref="Panel.Children"/> of our host panel.</param> protected void SetPreparedItems(bool setItems, ItemCollection preparedItems, bool setChildren, ItemCollection preparedChildren) { ItemCollection oldPreparedItems; ItemCollection oldPreparedChildren; lock (_renderLock) { oldPreparedItems = _preparedItems; oldPreparedChildren = _preparedChildren; _preparedItems = preparedItems; _preparedChildren = preparedChildren; _setItems = setItems; _setChildren = setChildren; } // If one of those oldXXX properties is set, this method was called multiple times before _preparedItems could be // used by UpdatePreparedItems, so dispose old items if (oldPreparedItems != null) { oldPreparedItems.Dispose(); } if (oldPreparedChildren != null) { oldPreparedChildren.Dispose(); } if (_elementState == ElementState.Preparing) { // Shortcut in state Preparing - no render thread necessary here to do the UpdatePreparedItems work UpdatePreparedItems(); } InvalidateLayout(true, true); }
/// <summary> /// Called when the <see cref="Items"/> collection changed. /// </summary> /// <param name="collection">The <see cref="Items"/> collection.</param> void OnItemsCollectionChanged(ItemCollection collection) { OnItemsChanged(); }