diff --git a/rhythmdb/rhythmdb-property-model.c b/rhythmdb/rhythmdb-property-model.c
index 82231fd..9aef011 100644
--- a/rhythmdb/rhythmdb-property-model.c
+++ b/rhythmdb/rhythmdb-property-model.c
@@ -41,11 +41,19 @@ G_DEFINE_TYPE_WITH_CODE(RhythmDBPropertyModel, rhythmdb_property_model, G_TYPE_O
 					      rhythmdb_property_model_tree_model_init)
 			G_IMPLEMENT_INTERFACE(RB_TYPE_TREE_DRAG_SOURCE,
 					      rhythmdb_property_model_drag_source_init))
-
+/*
+ * Structure for entries in the property model.
+ * The sort string is derived from one of a list of properties, so we
+ * store the index in the list of the property that gave us the current
+ * sort string, so that if a newly added entry has a value for a more preferred
+ * property, we can use that instead.  The sort property list should never
+ * get longer than 16, so 4 bits is more than enough to store this index.
+ */
 typedef struct {
 	RBRefString *string;
 	RBRefString *sort_string;
-	guint refcount;
+	guint sort_string_from : 4;
+	guint refcount : 28;
 } RhythmDBPropertyModelEntry;
 
 static void rhythmdb_property_model_dispose (GObject *object);
@@ -152,7 +160,7 @@ struct RhythmDBPropertyModelPrivate
 	GHashTable *entries;
 
 	RhythmDBPropType propid;
-	RhythmDBPropType sort_propid;
+	GArray *sort_propids;
 
 	guint stamp;
 
@@ -347,6 +355,13 @@ rhythmdb_property_model_set_query_model_internal (RhythmDBPropertyModel *model,
 }
 
 static void
+append_sort_property (RhythmDBPropertyModel *model, RhythmDBPropType prop)
+{
+	RhythmDBPropType p = prop;
+	g_array_append_val (model->priv->sort_propids, p);
+}
+
+static void
 rhythmdb_property_model_set_property (GObject *object,
 				      guint prop_id,
 				      const GValue *value,
@@ -362,20 +377,22 @@ rhythmdb_property_model_set_property (GObject *object,
 		model->priv->propid = g_value_get_int (value);
 		switch (model->priv->propid) {
 		case RHYTHMDB_PROP_GENRE:
-			model->priv->sort_propid = RHYTHMDB_PROP_GENRE;
+			append_sort_property (model, RHYTHMDB_PROP_GENRE);
 			break;
 		case RHYTHMDB_PROP_ARTIST:
-			model->priv->sort_propid = RHYTHMDB_PROP_ARTIST;
+			/* use artist-sortname where available */
+			append_sort_property (model, RHYTHMDB_PROP_ARTIST_SORTNAME);
+			append_sort_property (model, RHYTHMDB_PROP_ARTIST);
 			break;
 		case RHYTHMDB_PROP_ALBUM:
-			model->priv->sort_propid = RHYTHMDB_PROP_ALBUM;
+			append_sort_property (model, RHYTHMDB_PROP_ALBUM);
 			break;
 		case RHYTHMDB_PROP_SUBTITLE:
-			model->priv->sort_propid = RHYTHMDB_PROP_SUBTITLE;
+			append_sort_property (model, RHYTHMDB_PROP_SUBTITLE);
 			break;
 		case RHYTHMDB_PROP_TITLE:
 		case RHYTHMDB_PROP_LOCATION:
-			model->priv->sort_propid = RHYTHMDB_PROP_TITLE;
+			append_sort_property (model, RHYTHMDB_PROP_TITLE);
 			break;
 		default:
 			g_assert_not_reached ();
@@ -428,6 +445,8 @@ rhythmdb_property_model_init (RhythmDBPropertyModel *model)
 
 	model->priv->all = g_new0 (RhythmDBPropertyModelEntry, 1);
 	model->priv->all->string = rb_refstring_new (_("All"));
+
+	model->priv->sort_propids = g_array_new (FALSE, FALSE, sizeof (RhythmDBPropType));
 }
 
 static void
@@ -488,6 +507,8 @@ rhythmdb_property_model_finalize (GObject *object)
 
 	g_free (model->priv->all);
 
+	g_array_free (model->priv->sort_propids, TRUE);
+
 	G_OBJECT_CLASS (rhythmdb_property_model_parent_class)->finalize (object);
 }
 
@@ -579,6 +600,79 @@ rhythmdb_property_model_compare (RhythmDBPropertyModelEntry *a,
 	return strcmp (a_str, b_str);
 }
 
+/*
+ * looks for an updated sort string in a new entry for the specified
+ * property.  if the new entry provides a value for a higher priority
+ * sort property, updates the property to use the new sort string and
+ * returns TRUE.  otherwise, returns FALSE.
+ */
+static gboolean
+update_sort_string (RhythmDBPropertyModel *model,
+		    RhythmDBPropertyModelEntry *prop,
+		    RhythmDBEntry *entry)
+{
+	const char *newvalue = NULL;
+	int pi;
+	int upto;
+
+	/* we only need to check properties that are preferred to the one that
+	 * gave us the current sort string.
+	 */
+	upto = model->priv->sort_propids->len;
+	if (prop->sort_string != NULL) {
+		upto = prop->sort_string_from;
+	}
+
+	/* search for a non-empty sort string value */
+	for (pi = 0; pi < upto; pi++) {
+		RhythmDBPropType propid;
+
+		propid = g_array_index (model->priv->sort_propids, RhythmDBPropType, pi);
+		newvalue = rhythmdb_entry_get_string (entry, propid);
+		if (newvalue != NULL && newvalue[0] != '\0') {
+			break;
+		}
+	}
+
+	/* if we found one, replace the current sort string */
+	if (newvalue != NULL && (prop->sort_string == NULL || pi < prop->sort_string_from)) {
+		rb_debug ("replacing current sort string %s with %s (%d -> %d)",
+			  prop->sort_string ? rb_refstring_get (prop->sort_string) : "NULL",
+			  newvalue,
+			  prop->sort_string_from,
+			  pi);
+		if (prop->sort_string != NULL) {
+			rb_refstring_unref (prop->sort_string);
+		}
+		prop->sort_string = rb_refstring_new (newvalue);
+		prop->sort_string_from = pi;
+		return TRUE;
+	}
+	return FALSE;
+}
+
+/*
+ * to be called when a property's position in the sorted order may have changed.
+ * emits row-deleted, resorts the property sequence, and emits row-inserted.
+ */
+static void
+property_sort_changed (RhythmDBPropertyModel *model, GSequenceIter *ptr, GtkTreeIter *iter)
+{
+	GtkTreePath *path;
+
+	path = rhythmdb_property_model_get_path (GTK_TREE_MODEL (model), iter);
+	gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path);
+	gtk_tree_path_free (path);
+
+	g_sequence_sort_changed (ptr,
+				 (GCompareDataFunc) rhythmdb_property_model_compare,
+				 model);
+
+	path = rhythmdb_property_model_get_path (GTK_TREE_MODEL (model), iter);
+	gtk_tree_model_row_inserted (GTK_TREE_MODEL (model), path, iter);
+	gtk_tree_path_free (path);
+}
+
 static RhythmDBPropertyModelEntry *
 rhythmdb_property_model_insert (RhythmDBPropertyModel *model,
 				RhythmDBEntry *entry)
@@ -595,10 +689,15 @@ rhythmdb_property_model_insert (RhythmDBPropertyModel *model,
 	model->priv->all->refcount++;
 
 	if ((ptr = g_hash_table_lookup (model->priv->reverse_map, propstr))) {
+		iter.user_data = ptr;
 		prop = g_sequence_get (ptr);
 		prop->refcount++;
 		rb_debug ("adding \"%s\": refcount %d", propstr, prop->refcount);
 
+		if (update_sort_string (model, prop, entry)) {
+			property_sort_changed (model, ptr, &iter);
+		}
+
 		iter.user_data = ptr;
 		path = rhythmdb_property_model_get_path (GTK_TREE_MODEL (model), &iter);
 		gtk_tree_model_row_changed (GTK_TREE_MODEL (model), path, &iter);
@@ -610,7 +709,7 @@ rhythmdb_property_model_insert (RhythmDBPropertyModel *model,
 
 	prop = g_new0 (RhythmDBPropertyModelEntry, 1);
 	prop->string = rb_refstring_new (propstr);
-	prop->sort_string = rb_refstring_new (rhythmdb_entry_get_string (entry, model->priv->sort_propid));
+	update_sort_string (model, prop, entry);
 	prop->refcount = 1;
 
 	ptr = g_sequence_insert_sorted (model->priv->properties, prop,
