我有一个ViewModel
,其中包含一个绑定到View
中控件的ObservableCollection<CustomKeyGroup<CustomItem>>
属性。问题在于,我想按CustomKeyGroup<T>
中的属性对此集合进行排序,而不需要设置ObservableCollection<...>
对象属性(即内联地对集合进行排序):
public class MainViewModel : ViewModelBase {
... // data service etc code
private ObservableCollection<CustomKeyGroup<CustomItem>> _items = new ObservableCollection<CustomKeyGroup<CustomItem>>();
public ObservableCollection<CustomKeyGroup<CustomItem>> Items
{
get
{
return _items;
}
set
{
_items = value;
RaisePropertyChanged("Items");
}
}
public void Sort(string _orderBy = null, bool _descending = true) {
if (string.IsNullOrEmpty(_orderBy) || this.Items.Count == 0) {
return;
}
var test = this.Items.ToList();
// bubble sort
try {
for (int i = test.Count - 1; i >= 0; i--) {
for (int j = 1; j <= i; j++) {
CustomKeyGroup<CustomItem> o1 = test[j - 1];
CustomKeyGroup<CustomItem> o2 = test[j];
bool move = false;
var order = typeof(CustomKeyGroup<CustomItem>).GetProperty(orderBy);
var t = order.GetValue(o1);
var t2 = order.GetValue(o2);
// sort comparisons depending on property
if (_descending) { // ascending
if (t.GetType() == typeof(int)) { // descending and int property
if ((int)t < (int)t2) {
move = true;
}
} else { // descending and string property
if (t.ToString().CompareTo(t2.ToString()) > 0) {
move = true;
}
}
} else { // ascending
if (t.GetType() == typeof(int)) { // ascending and int property
if ((int)t > (int)t2) {
move = true;
}
} else { // ascending and string property
if (t.ToString().CompareTo(t2.ToString()) < 0) {
move = true;
}
}
}
// swap elements
if (move) {
//this.Items.Move(j - 1, j); // "inline"
test[j] = o1;
test[j - 1] = o2;
}
}
}
// set property to raise property changed event
this.Items = new ObservableCollection<CustomKeyGroup<CustomItem>>(test);
} catch (Exception) {
Debug.WriteLine("Sorting error");
}
//RaisePropertyChanged("Items"); // "inline sort" raise property changed to update Data binding
Debug.WriteLine("Sorted complete");
}
... // get data from service, etc.
从上面的代码中可以看出,尝试的内联排序被注释掉了(因为它们不会更新数据绑定到它的控件),而手动设置
Items
则保留下来了(虽然可以工作,但如果你滚动控件并进行排序,它将带你回到顶部 - 这是不可取的!)。有人知道如何使用内联排序选项更新视图/控件吗?我也尝试过手动引发
RaisePropertyChanged
事件(在ObservableObject
中指定,使用MVVMLight Toolkit),但没有成功。注意:在
try-catch
的结尾处设置断点可以发现,ObservableCollection<...>
确实已经排序,但更改只是不反映在View
中!更奇怪的是,控件(LongListSelector
)具有绑定到CustomKeyGroup<T>
的另一个属性的JumpList
,并且它成功地立即更新了!如果我点击JumpList
中的任何一个项目,则View
正确地更新自己,显示排序后的项目......然后我想到在排序后设置View
的DataContext
,但这也无法解决问题。谢谢。
NotifyCollectionChanged
),但显然并非如此。它只是从视图中删除元素,而不更新顺序!我想这在ObervableCollection
的实现中是有道理的,因为Move
会引发CollectionChanged
。 - Travis Liew