我有一个很好的WPF DataGrid绑定到一个对象集合。一切正常,当任何对象的属性改变时,网格都会更新。问题是当更新发生时行不会重新排序,然后排序不再有效。
关于如何解决这个问题的想法?
提前致谢。
编辑:这就是我绑定DataGrid的方式:
<Controls:DataGrid MinHeight="300" MinWidth="300" ItemsSource="{Binding Data}" AutoGenerateColumns="True">
public class MainWindowViewModel
{
public ObservableCollectionMultiThread<StockViewModel> Data { get; private set; }
}
public class ObservableCollectionMultiThread<T> : ObservableCollection<T>
{
// Override the event so this class can access it
public override event System.Collections.Specialized.NotifyCollectionChangedEventHandler CollectionChanged;
protected override void OnCollectionChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
// Be nice - use BlockReentrancy like MSDN said
using (base.BlockReentrancy())
{
System.Collections.Specialized.NotifyCollectionChangedEventHandler eventHandler = this.CollectionChanged;
if (eventHandler == null)
return;
Delegate[] delegates = eventHandler.GetInvocationList();
// Walk thru invocation list
foreach (System.Collections.Specialized.NotifyCollectionChangedEventHandler handler in delegates)
{
DispatcherObject dispatcherObject = handler.Target as DispatcherObject;
// If the subscriber is a DispatcherObject and different thread
if (dispatcherObject != null && dispatcherObject.CheckAccess() == false)
{
// Invoke handler in the target dispatcher's thread
dispatcherObject.Dispatcher.Invoke(DispatcherPriority.DataBind, handler, this, e);
}
else // Execute handler as is
handler(this, e);
}
}
}
}
PD:我使用的是2008年10月的CTP DataGrid,因为我使用的是Net 3.5
答案 0 :(得分:1)
通常,WPF上的控件不响应项目版本。我已经使用这个类作为网格的源:
using System;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Windows.Data;
using System.Windows.Threading;
namespace StockCrawler
{
public class AutoRefreshListCollectionView : ListCollectionView
{
public AutoRefreshListCollectionView(IList list)
: base(list)
{
this.SubscribeSourceEvents(list, false);
}
private void Item_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
bool refresh = false;
foreach (SortDescription sort in this.SortDescriptions)
{
if (sort.PropertyName == e.PropertyName)
{
refresh = true;
break;
}
}
if (!refresh)
{
foreach (GroupDescription group in this.GroupDescriptions)
{
PropertyGroupDescription propertyGroup = group as PropertyGroupDescription;
if (propertyGroup != null && propertyGroup.PropertyName == e.PropertyName)
{
refresh = true;
break;
}
}
}
if (refresh)
{
if (!this.Dispatcher.CheckAccess())
{
// Invoke handler in the target dispatcher's thread
this.Dispatcher.Invoke((Action)this.Refresh);
}
else // Execute handler as is
{
this.Refresh();
}
}
}
private void Source_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Add)
{
this.SubscribeItemsEvents(e.NewItems, false);
}
else if (e.Action == NotifyCollectionChangedAction.Remove)
{
this.SubscribeItemsEvents(e.OldItems, true);
}
else
{
// TODO: Support this
}
}
private void SubscribeItemEvents(object item, bool remove)
{
INotifyPropertyChanged notify = item as INotifyPropertyChanged;
if (notify != null)
{
if (remove)
{
notify.PropertyChanged -= this.Item_PropertyChanged;
}
else
{
notify.PropertyChanged += this.Item_PropertyChanged;
}
}
}
private void SubscribeItemsEvents(IEnumerable items, bool remove)
{
foreach (object item in items)
{
this.SubscribeItemEvents(item, remove);
}
}
private void SubscribeSourceEvents(object source, bool remove)
{
INotifyCollectionChanged notify = source as INotifyCollectionChanged;
if (notify != null)
{
if (remove)
{
notify.CollectionChanged -= this.Source_CollectionChanged;
}
else
{
notify.CollectionChanged += this.Source_CollectionChanged;
}
}
this.SubscribeItemsEvents((IEnumerable)source, remove);
}
}
}