diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityListController.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityListController.php
index 3977310..5c2f213 100644
--- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityListController.php
+++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityListController.php
@@ -8,6 +8,8 @@
 namespace Drupal\Core\Config\Entity;
 
 use Drupal\Core\Entity\EntityListController;
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\EntityStorageControllerInterface;
 
 /**
  * Defines the default list controller for ConfigEntity objects.
@@ -15,7 +17,29 @@
 class ConfigEntityListController extends EntityListController {
 
   /**
-   * Overrides Drupal\Core\Entity\EntityListController::load().
+   * Name of the entity's weight field or FALSE if no field is provided.
+   *
+   * @var string|bool
+   */
+  protected $weightKey;
+
+  /**
+   * Overrides EntityListController::__construct().
+   */
+  public function __construct($entity_type, EntityStorageControllerInterface $storage) {
+    parent::__construct($entity_type, $storage);
+
+    // Check if the entity type supports weighting.
+    if (!empty($this->entityInfo['entity_keys']['weight'])) {
+      $this->weightKey = $this->entityInfo['entity_keys']['weight'];
+    }
+    else {
+      $this->weightKey = FALSE;
+    }
+  }
+
+  /**
+   * Overrides EntityListController::load().
    */
   public function load() {
     $entities = parent::load();
@@ -23,4 +47,135 @@ public function load() {
     return $entities;
   }
 
+  /**
+   * Overrides EntityListController::buildHeader().
+   */
+  public function buildHeader() {
+    $row = parent::buildHeader();
+    // Override defaults.
+    $row['label'] = $this->entityInfo['label'];
+    unset($row['id']);
+    if (empty($this->weightKey)) {
+      return $row;
+    }
+    // @todo Simplify this http://drupal.org/node/1876718
+    return $row = array_slice($row, 0, 2, TRUE) + array(
+      'weight' => t('Weight'),
+    ) + array_slice($row, 0, NULL, TRUE);
+  }
+
+  /**
+   * Overrides EntityListController::buildRow().
+   */
+  public function buildRow(EntityInterface $entity) {
+    $row = parent::buildRow($entity);
+    // Configurable entities could have default link to their edit pages.
+    if ($uri = $entity->uri()) {
+      $row['label'] = array('data' => array(
+        '#type' => 'link',
+        '#title' => $row['label'],
+        '#href' => $uri['path'],
+        '#options' => $uri['options'],
+      ));
+    }
+    else {
+      $row['label'] = array('data' => array(
+        '#markup' => check_plain($row['label']),
+      ));
+    }
+    unset($row['id']);
+    if (empty($this->weightKey)) {
+      return $row;
+    }
+    // Override default values to markup elements.
+    $row['#attributes']['class'][] = 'draggable';
+    $row['#weight'] = $entity->get($this->weightKey);
+    // Add weight column.
+    $row['weight'] = array(
+      '#type' => 'weight',
+      '#title' => t('Weight for @title', array('@title' => $entity->label())),
+      '#title_display' => 'invisible',
+      '#default_value' => $entity->get($this->weightKey),
+      '#attributes' => array('class' => array('weight')),
+    );
+    return $row;
+  }
+
+  /**
+   * Overrides EntityListController::render().
+   */
+  public function render() {
+    if (empty($this->weightKey)) {
+      return parent::render();
+    }
+
+    $form_state = array();
+    $form_state['build_info']['args'] = array();
+    $form_state['build_info']['callback'] = array($this, 'form');
+
+    return drupal_build_form($this->entityType . '_list_form', $form_state);
+  }
+
+  /**
+   * Creates a tabledrag form for manipulating config entity weights.
+   *
+   * @param array $form
+   *   An associative array containing the structure of the form.
+   * @param array $form_state
+   *   A reference to a keyed array containing the current state of the form.
+   *
+   * @return array
+   *   The array containing the complete form.
+   */
+  public function form($form, &$form_state) {
+    $form['entities'] = array(
+      '#type' => 'table',
+      '#header' => $this->buildHeader(),
+      '#empty' => t('There is no @label yet.', array('@label' => $this->entityInfo['label'])),
+      '#tabledrag' => array(
+        array('order', 'sibling', 'weight'),
+      ),
+    );
+
+    // Save header's order of columns for sorting data-rows.
+    $header_sort = array_flip(array_keys($form['entities']['#header']));
+    foreach ($this->load() as $entity) {
+      $row = $this->buildRow($entity);
+      // Sort row columns by header's order.
+      $form['entities'][$entity->id()] = array_merge($header_sort, $row);
+    }
+
+    $form['actions']['#type'] = 'actions';
+    $form['actions']['submit'] = array(
+      '#type' => 'submit',
+      '#value' => t('Save'),
+      '#submit' => array(array($this, 'submit')),
+      '#button_type' => 'primary',
+    );
+
+    return $form;
+  }
+
+  /**
+   * Submit handler for the overview form.
+   *
+   * @param array $form
+   *   An associative array containing the structure of the form.
+   * @param array $form_state
+   *   A reference to a keyed array containing the current state of the form.
+   */
+  public function submit($form, &$form_state) {
+    $values = $form_state['values']['entities'];
+
+    $entities = entity_load_multiple($this->entityType, array_keys($values));
+    foreach ($values as $id => $value) {
+      if (isset($entities[$id])) {
+        $entities[$id]->set($this->weightKey, $value['weight']);
+        $entities[$id]->save();
+      }
+    }
+
+    drupal_set_message(t('The configuration options have been saved.'));
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Entity/EntityListController.php b/core/lib/Drupal/Core/Entity/EntityListController.php
index 354b27a..394d566 100644
--- a/core/lib/Drupal/Core/Entity/EntityListController.php
+++ b/core/lib/Drupal/Core/Entity/EntityListController.php
@@ -112,8 +112,7 @@ public function buildHeader() {
   public function buildRow(EntityInterface $entity) {
     $row['label'] = $entity->label();
     $row['id'] = $entity->id();
-    $operations = $this->buildOperations($entity);
-    $row['operations']['data'] = $operations;
+    $row['operations']['data'] = $this->buildOperations($entity);
     return $row;
   }
 
@@ -153,8 +152,12 @@ public function render() {
       '#rows' => array(),
       '#empty' => t('There is no @label yet.', array('@label' => $this->entityInfo['label'])),
     );
+    // Save header's order of columns for sorting data-rows.
+    $header_sort = array_flip(array_keys($build['#header']));
     foreach ($this->load() as $entity) {
-      $build['#rows'][$entity->id()] = $this->buildRow($entity);
+      $row = $this->buildRow($entity);
+      // Sort row columns by the header's order.
+      $build['#rows'][$entity->id()] = array_merge($header_sort, $row);
     }
     return $build;
   }
diff --git a/core/lib/Drupal/Core/Entity/EntityManager.php b/core/lib/Drupal/Core/Entity/EntityManager.php
index 42e4d77..135a59e 100644
--- a/core/lib/Drupal/Core/Entity/EntityManager.php
+++ b/core/lib/Drupal/Core/Entity/EntityManager.php
@@ -103,6 +103,8 @@
  *   - uuid (optional): The name of the property that contains the universally
  *     unique identifier of the entity, which is used to distinctly identify
  *     an entity across different systems.
+ *   - weight (optional): The name of the property that contains the weight of
+ *     the configuration entity which is used to for ordering.
  * - bundle_keys: An array describing how the Field API can extract the
  *   information it needs from the bundle objects for this type (e.g
  *   Vocabulary objects for terms; not applicable for nodes). This entry can
diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigEntityListTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigEntityListTest.php
index f19c03d..831bd2d 100644
--- a/core/modules/config/lib/Drupal/config/Tests/ConfigEntityListTest.php
+++ b/core/modules/config/lib/Drupal/config/Tests/ConfigEntityListTest.php
@@ -70,21 +70,24 @@ function testList() {
     $this->assertIdentical($expected_operations, $actual_operations, 'Return value from getOperations matches expected.');
 
     // Test buildHeader() method.
+    $entity_info = entity_get_info('config_test');
     $expected_items = array(
-      'label' => 'Label',
-      'id' => 'Machine name',
+      'label' => $entity_info['label'],
       'operations' => 'Operations',
     );
     $actual_items = $controller->buildHeader();
     $this->assertIdentical($expected_items, $actual_items, 'Return value from buildHeader matches expected.');
 
     // Test buildRow() method.
-    $build_operations = $controller->buildOperations($entity);
     $expected_items = array(
-      'label' => 'Default',
-      'id' => 'default',
+      'label' => array('data' => array(
+        '#type' => 'link',
+        '#title' => 'Default',
+        '#href' => $uri['path'],
+        '#options' => $uri['options'],
+      )),
       'operations' => array(
-        'data' => $build_operations,
+        'data' => $controller->buildOperations($entity),
       ),
     );
     $actual_items = $controller->buildRow($entity);
@@ -110,24 +113,25 @@ function testListUI() {
 
     // Test the table header.
     $elements = $this->xpath('//div[@id="content"]//table/thead/tr/th');
-    $this->assertEqual(count($elements), 3, 'Correct number of table header cells found.');
+    $this->assertEqual(count($elements), 2, 'Correct number of table header cells found.');
 
     // Test the contents of each th cell.
-    $expected_items = array('Label', 'Machine name', 'Operations');
+    $entity_info = entity_get_info('config_test');
+    $expected_items = array($entity_info['label'], 'Operations');
     foreach ($elements as $key => $element) {
       $this->assertIdentical((string) $element[0], $expected_items[$key]);
     }
 
     // Check the number of table row cells.
     $elements = $this->xpath('//div[@id="content"]//table/tbody/tr[@class="odd"]/td');
-    $this->assertEqual(count($elements), 3, 'Correct number of table row cells found.');
+    $this->assertEqual(count($elements), 2, 'Correct number of table row cells found.');
 
     // Check the contents of each row cell. The first cell contains the label,
     // the second contains the machine name, and the third contains the
     // operations list.
-    $this->assertIdentical((string) $elements[0], 'Default');
-    $this->assertIdentical((string) $elements[1], 'default');
-    $this->assertTrue($elements[2]->children()->xpath('//ul'), 'Operations list found.');
+    $title = $elements[0]->children();
+    $this->assertIdentical((string) $title, 'Default');
+    $this->assertTrue($elements[1]->children()->xpath('//ul'), 'Operations list found.');
 
     // Add a new entity using the operations link.
     $this->assertLink('Add test configuration');
@@ -139,8 +143,7 @@ function testListUI() {
     // Confirm that the user is returned to the listing, and verify that the
     // text of the label and machine name appears in the list (versus elsewhere
     // on the page).
-    $this->assertFieldByXpath('//td', 'Antelope', "Label found for added 'Antelope' entity.");
-    $this->assertFieldByXpath('//td', 'antelope', "Machine name found for added 'Antelope' entity.");
+    $this->assertFieldByXpath('//td/a', 'Antelope', "Label found for added 'Antelope' entity.");
 
     // Edit the entity using the operations link.
     $this->assertLink('Edit');
@@ -153,8 +156,7 @@ function testListUI() {
     // Confirm that the user is returned to the listing, and verify that the
     // text of the label and machine name appears in the list (versus elsewhere
     // on the page).
-    $this->assertFieldByXpath('//td', 'Albatross', "Label found for updated 'Albatross' entity.");
-    $this->assertFieldByXpath('//td', 'albatross', "Machine name found for updated 'Albatross' entity.");
+    $this->assertFieldByXpath('//td/a', 'Albatross', "Label found for updated 'Albatross' entity.");
 
     // Delete the added entity using the operations link.
     $this->assertLink('Delete');
@@ -166,7 +168,6 @@ function testListUI() {
     // Verify that the text of the label and machine name does not appear in
     // the list (though it may appear elsewhere on the page).
     $this->assertNoFieldByXpath('//td', 'Albatross', "No label found for deleted 'Albatross' entity.");
-    $this->assertNoFieldByXpath('//td', 'albatross', "No machine name found for deleted 'Albatross' entity.");
 
     // Delete the original entity using the operations link.
     $this->clickLink('Delete');
@@ -177,7 +178,6 @@ function testListUI() {
     // Verify that the text of the label and machine name does not appear in
     // the list (though it may appear elsewhere on the page).
     $this->assertNoFieldByXpath('//td', 'Default', "No label found for deleted 'Default' entity.");
-    $this->assertNoFieldByXpath('//td', 'default', "No machine name found for deleted 'Default' entity.");
 
     // Confirm that the empty text is displayed.
     $this->assertText('There is no Test configuration yet.');
diff --git a/core/modules/contact/lib/Drupal/contact/CategoryListController.php b/core/modules/contact/lib/Drupal/contact/CategoryListController.php
index a3ec886..b96d5dd 100644
--- a/core/modules/contact/lib/Drupal/contact/CategoryListController.php
+++ b/core/modules/contact/lib/Drupal/contact/CategoryListController.php
@@ -1,7 +1,7 @@
 <?php
 
 /**
- * Definition of Drupal\contact\CategoryListController.
+ * Contains \Drupal\contact\CategoryListController.
  */
 
 namespace Drupal\contact;
@@ -15,7 +15,7 @@
 class CategoryListController extends ConfigEntityListController {
 
   /**
-   * Overrides Drupal\Core\Entity\EntityListController::getOperations().
+   * Overrides \Drupal\Core\Entity\EntityListController::getOperations().
    */
   public function getOperations(EntityInterface $entity) {
     $operations = parent::getOperations($entity);
@@ -38,26 +38,33 @@ public function getOperations(EntityInterface $entity) {
   }
 
   /**
-   * Overrides Drupal\Core\Entity\EntityListController::buildHeader().
+   * Overrides ConfigEntityListController::buildHeader().
    */
   public function buildHeader() {
-    $row['category'] = t('Category');
-    $row['recipients'] = t('Recipients');
-    $row['selected'] = t('Selected');
-    $row['operations'] = t('Operations');
-    return $row;
+    $row = parent::buildHeader();
+    // The two array_slice work together to put additional columns after the
+    // first ones.
+    // @todo Simplify this http://drupal.org/node/1876718
+    return array_slice($row, 0, 1, TRUE) + array(
+      'default' => t('Default'),
+      'recipients' => t('Recipients'),
+    ) + array_slice($row, 0, NULL, TRUE);
   }
 
   /**
-   * Overrides Drupal\Core\Entity\EntityListController::buildRow().
+   * Overrides ConfigEntityListController::buildRow().
    */
   public function buildRow(EntityInterface $entity) {
-    $row['category'] = check_plain($entity->label());
-    $row['recipients'] = check_plain(implode(', ', $entity->recipients));
     $default_category = config('contact.settings')->get('default_category');
-    $row['selected'] = ($default_category == $entity->id() ? t('Yes') : t('No'));
-    $row['operations']['data'] = $this->buildOperations($entity);
-    return $row;
+    // Add own columns.
+    return parent::buildRow($entity) + array(
+      'default' => array(
+        '#markup' => ($default_category == $entity->id() ? t('Yes') : t('No')),
+      ),
+      'recipients' => array(
+        '#markup' => check_plain(implode(', ', $entity->recipients)),
+      ),
+    );
   }
 
 }
diff --git a/core/modules/contact/lib/Drupal/contact/Plugin/Core/Entity/Category.php b/core/modules/contact/lib/Drupal/contact/Plugin/Core/Entity/Category.php
index 0004b00..89cd767 100644
--- a/core/modules/contact/lib/Drupal/contact/Plugin/Core/Entity/Category.php
+++ b/core/modules/contact/lib/Drupal/contact/Plugin/Core/Entity/Category.php
@@ -28,7 +28,8 @@
  *   entity_keys = {
  *     "id" = "id",
  *     "label" = "label",
- *     "uuid" = "uuid"
+ *     "uuid" = "uuid",
+ *     "weight" = "weight"
  *   }
  * )
  */
diff --git a/core/modules/menu/lib/Drupal/menu/MenuListController.php b/core/modules/menu/lib/Drupal/menu/MenuListController.php
index b64dbd0..88bafbd 100644
--- a/core/modules/menu/lib/Drupal/menu/MenuListController.php
+++ b/core/modules/menu/lib/Drupal/menu/MenuListController.php
@@ -15,28 +15,27 @@
 class MenuListController extends ConfigEntityListController {
 
   /**
-   * Overrides \Drupal\Core\Entity\EntityListController::buildHeader().
+   * Overrides ConfigEntityListController::buildHeader().
    */
   public function buildHeader() {
-    $row['title'] = t('Title');
-    $row['description'] = array(
-      'data' => t('Description'),
-      'class' => array(RESPONSIVE_PRIORITY_MEDIUM),
-    );
-    $row['operations'] = t('Operations');
-    return $row;
+    $row = parent::buildHeader();
+    // Add description column after first too.
+    // @todo Simplify this http://drupal.org/node/1876718
+    return array_slice($row, 0, 1, TRUE) + array(
+      'description' => array(
+        'data' => t('Description'),
+        'class' => array(RESPONSIVE_PRIORITY_MEDIUM),
+      ),
+    ) + array_slice($row, 0, NULL, TRUE);
   }
 
   /**
-   * Overrides \Drupal\Core\Entity\EntityListController::buildRow().
+   * Overrides ConfigEntityListController::buildRow().
    */
   public function buildRow(EntityInterface $entity) {
-    $row['title'] = array(
-      'data' => check_plain($entity->label()),
-      'class' => array('menu-label'),
-    );
+    $row = parent::buildRow($entity);
+    $row['label']['class'] = array('menu-label');
     $row['description'] = filter_xss_admin($entity->description);
-    $row['operations']['data'] = $this->buildOperations($entity);
     return $row;
   }
 
@@ -67,7 +66,7 @@ public function getOperations(EntityInterface $entity) {
   }
 
   /**
-   * Overrides \Drupal\Core\Entity\EntityListController::render();
+   * Overrides ConfigEntityListController::render();
    */
   public function render() {
     $build = parent::render();
diff --git a/core/modules/shortcut/lib/Drupal/shortcut/ShortcutListController.php b/core/modules/shortcut/lib/Drupal/shortcut/ShortcutListController.php
index 401d280..3a1a6cf 100644
--- a/core/modules/shortcut/lib/Drupal/shortcut/ShortcutListController.php
+++ b/core/modules/shortcut/lib/Drupal/shortcut/ShortcutListController.php
@@ -15,47 +15,25 @@
 class ShortcutListController extends ConfigEntityListController {
 
   /**
-   * Overrides \Drupal\Core\Entity\EntityListController::buildHeader().
-   */
-  public function buildHeader() {
-    $row['label'] = t('Name');
-    $row['operations'] = t('Operations');
-    return $row;
-  }
-
-  /**
    * Overrides \Drupal\Core\Entity\EntityListController::getOperations().
    */
   public function getOperations(EntityInterface $entity) {
+    $operations = parent::getOperations($entity);
     $uri = $entity->uri();
     $operations['list'] = array(
       'title' => t('list links'),
       'href' => $uri['path'],
-    );
-    $operations['edit'] = array(
-      'title' => t('edit set'),
-      'href' => $uri['path'] . '/edit',
       'options' => $uri['options'],
-      'weight' => 10,
+      'weight' => 0,
     );
+    $operations['edit']['title'] = t('edit set');
     if (shortcut_set_delete_access($entity)) {
-      $operations['delete'] = array(
-        'title' => t('delete set'),
-        'href' => $uri['path'] . '/delete',
-        'options' => $uri['options'],
-        'weight' => 100,
-      );
+      $operations['delete']['title'] = t('delete set');
+    }
+    else {
+      unset($operations['delete']);
     }
     return $operations;
   }
 
-  /**
-   * Overrides \Drupal\Core\Entity\EntityListController::buildRow().
-   */
-  public function buildRow(EntityInterface $entity) {
-    $row['name'] = check_plain($entity->label());
-    $row['operations']['data'] = $this->buildOperations($entity);
-    return $row;
-  }
-
 }
