diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp
index 2b6c80bac809bc36db1253122c77a914d8894b03..a471158c3d49e9eea4e0f094e8bfc4682f44269f 100644
--- a/indra/newview/lloutfitslist.cpp
+++ b/indra/newview/lloutfitslist.cpp
@@ -1055,25 +1055,37 @@ void LLOutfitsList::onWearableItemsListRightClick(LLUICtrl* ctrl, S32 x, S32 y)
 
 void LLOutfitsList::onCOFChanged()
 {
-	LLInventoryModel::changed_items_t changed_linked_items;
+	LLInventoryModel::cat_array_t cat_array;
+	LLInventoryModel::item_array_t item_array;
 
-	const LLInventoryModel::changed_items_t& changed_items = gInventory.getChangedIDs();
-	for (LLInventoryModel::changed_items_t::const_iterator iter = changed_items.begin();
-		 iter != changed_items.end();
-		 ++iter)
+	// Collect current COF items
+	gInventory.collectDescendents(
+		LLAppearanceMgr::instance().getCOF(),
+		cat_array,
+		item_array,
+		LLInventoryModel::EXCLUDE_TRASH);
+
+	uuid_vec_t vnew;
+	uuid_vec_t vadded;
+	uuid_vec_t vremoved;
+
+	// From gInventory we get the UUIDs of links that are currently in COF.
+	// These links UUIDs are not the same UUIDs that we have in each wearable items list.
+	// So we collect base items' UUIDs to find them or links that point to them in wearable
+	// items lists and update their worn state there.
+	for (LLInventoryModel::item_array_t::const_iterator iter = item_array.begin();
+		iter != item_array.end();
+		++iter)
 	{
-		LLViewerInventoryItem* item = gInventory.getItem(*iter);
-		if (item)
-		{
-			// From gInventory we get the UUIDs of new links added to COF
-			// or removed from COF. These links UUIDs are not the same UUIDs
-			// that we have in each wearable items list. So we collect base items
-			// UUIDs to find all items or links that point to same base items in wearable
-			// items lists and update their worn state there.
-			changed_linked_items.insert(item->getLinkedUUID());
-		}
+		vnew.push_back((*iter)->getLinkedUUID());
 	}
 
+	// We need to update only items that were added or removed from COF.
+	LLCommonUtils::computeDifference(vnew, mCOFLinkedItems, vadded, vremoved);
+
+	// Store the ids of items currently linked from COF.
+	mCOFLinkedItems = vnew;
+
 	for (outfits_map_t::iterator iter = mOutfitsMap.begin();
 			iter != mOutfitsMap.end();
 			++iter)
@@ -1084,9 +1096,13 @@ void LLOutfitsList::onCOFChanged()
 		LLWearableItemsList* list = dynamic_cast<LLWearableItemsList*>(tab->getAccordionView());
 		if (!list) continue;
 
+		// Append removed ids to added ids because we should update all of them.
+		vadded.reserve(vadded.size() + vremoved.size());
+		vadded.insert(vadded.end(), vremoved.begin(), vremoved.end());
+
 		// Every list updates the labels of changed items  or
 		// the links that point to these items.
-		list->updateChangedItems(changed_linked_items);
+		list->updateChangedItems(vadded);
 	}
 }
 
diff --git a/indra/newview/lloutfitslist.h b/indra/newview/lloutfitslist.h
index 206854b2326c1936630e44854c8f43af09f8567a..4613bdfeb9ba46293ff97f04a18268e5f8a90bb8 100644
--- a/indra/newview/lloutfitslist.h
+++ b/indra/newview/lloutfitslist.h
@@ -214,6 +214,10 @@ class LLOutfitsList : public LLPanelAppearanceTab
 	typedef outfits_map_t::value_type					outfits_map_value_t;
 	outfits_map_t					mOutfitsMap;
 
+	// IDs of original items which are worn and linked in COF.
+	// Used to monitor COF changes for updating items worn state. See EXT-8636.
+	uuid_vec_t						mCOFLinkedItems;
+
 	LLOutfitListGearMenu*			mGearMenu;
 	LLListContextMenu*				mOutfitMenu;
 
diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp
index 5e23965f625cb100127aee5489ef3c995c8f9245..bff4b9bcbd12bfad0b4acac8f7de4bbb4f20ed21 100644
--- a/indra/newview/llwearableitemslist.cpp
+++ b/indra/newview/llwearableitemslist.cpp
@@ -124,7 +124,11 @@ void LLPanelWearableOutfitItem::updateItem(const std::string& name,
 {
 	std::string search_label = name;
 
-	if (mWornIndicationEnabled && get_is_item_worn(mInventoryItemUUID))
+	// Updating item's worn status depending on whether it is linked in COF or not.
+	// We don't use get_is_item_worn() here because this update is triggered by
+	// an inventory observer upon link in COF beind added or removed so actual
+	// worn status of a linked item may still remain unchanged.
+	if (mWornIndicationEnabled && LLAppearanceMgr::instance().isLinkInCOF(mInventoryItemUUID))
 	{
 		search_label += LLTrans::getString("worn");
 		item_state = IS_WORN;
@@ -659,7 +663,7 @@ void LLWearableItemsList::updateList(const LLUUID& category_id)
 	refreshList(item_array);
 }
 
-void LLWearableItemsList::updateChangedItems(const LLInventoryModel::changed_items_t& changed_items_uuids)
+void LLWearableItemsList::updateChangedItems(const uuid_vec_t& changed_items_uuids)
 {
 	// nothing to update
 	if (changed_items_uuids.empty()) return;
@@ -681,7 +685,7 @@ void LLWearableItemsList::updateChangedItems(const LLInventoryModel::changed_ite
 
 		LLUUID linked_uuid = inv_item->getLinkedUUID();
 
-		for (LLInventoryModel::changed_items_t::const_iterator iter = changed_items_uuids.begin();
+		for (uuid_vec_t::const_iterator iter = changed_items_uuids.begin();
 				iter != changed_items_uuids.end();
 				++iter)
 		{
diff --git a/indra/newview/llwearableitemslist.h b/indra/newview/llwearableitemslist.h
index 237ba1af437fd45f43dff042a8acd916493621f9..ac4eac4764f63981450c47fe43781a082c8b3737 100644
--- a/indra/newview/llwearableitemslist.h
+++ b/indra/newview/llwearableitemslist.h
@@ -39,7 +39,6 @@
 // newview
 #include "llinventoryitemslist.h"
 #include "llinventorylistitem.h"
-#include "llinventorymodel.h"
 #include "lllistcontextmenu.h"
 #include "llwearabletype.h"
 
@@ -441,7 +440,7 @@ class LLWearableItemsList : public LLInventoryItemsList
 	 * Update items that match UUIDs from changed_items_uuids
 	 * or links that point at such items.
 	 */
-	void updateChangedItems(const LLInventoryModel::changed_items_t& changed_items_uuids);
+	void updateChangedItems(const uuid_vec_t& changed_items_uuids);
 
 	bool isStandalone() const { return mIsStandalone; }