Silverlight Datagrid:当该列被排序时突出显示整个列
问题描述:
我在我的Silverlight应用程序中有一个DataGrid,我想在该列进行排序时突出显示整列。Silverlight Datagrid:当该列被排序时突出显示整个列
它在概念上与前面的问题类似:Silverlight DataGrid: Highlight an entire column。
任何想法?我想过可能将一个行为附加到LayoutUpdated事件并检查单元格以查看它是否在排序列中?
答
有几个问题需要解决,以便做你想做的事情。最大的问题是,找出列的排序时间应该会更困难。我发现唯一的方法是识别列被排序,使其DataGrid.ItemsSource
为PagedCollectionView并在其SortDescriptions
属性上侦听CollectionChanged
事件。如果您的ItemsSource使用PagedCollectionView
,并且可以排序的所有列都是DataGridBoundColumn
(实际上是TemplateColumn以外的任何预构造),则此行为应该与您想要执行的操作相当接近。
public class DataGridSortedColumnHighlightBehavior : Behavior<DataGrid>
{
private List<DataGridRow> rows = new List<DataGridRow>();
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.LoadingRow += AssociatedObject_LoadingRow;
AssociatedObject.UnloadingRow += AssociatedObject_UnloadingRow;
if (AssociatedObject.ItemsSource == null)
{
AssociatedObject.LayoutUpdated += AssociatedObject_LayoutUpdated;
}
else
{
var collection =
((AssociatedObject.ItemsSource as PagedCollectionView).SortDescriptions as INotifyCollectionChanged);
collection.CollectionChanged += DataGridSortedColumnHighlightBehavior_CollectionChanged;
}
}
void AssociatedObject_UnloadingRow(object sender, DataGridRowEventArgs e)
{
rows.Remove(e.Row);
}
void AssociatedObject_LoadingRow(object sender, DataGridRowEventArgs e)
{
rows.Add(e.Row);
}
private void AssociatedObject_LayoutUpdated(object sender, EventArgs e)
{
if (AssociatedObject.ItemsSource != null)
{
AssociatedObject.LayoutUpdated -= AssociatedObject_LayoutUpdated;
var collection =
((AssociatedObject.ItemsSource as PagedCollectionView).SortDescriptions as INotifyCollectionChanged);
collection.CollectionChanged += DataGridSortedColumnHighlightBehavior_CollectionChanged;
}
}
void DataGridSortedColumnHighlightBehavior_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if(e.NewItems != null)
{
foreach(SortDescription sortDesc in e.NewItems)
{
foreach(var column in AssociatedObject.Columns)
{
var boundColumn = column as DataGridBoundColumn;
if (boundColumn == null)
continue;
if (boundColumn.Binding.Path.Path == sortDesc.PropertyName)
{
foreach (var row in rows)
ColorCell(column,row,Colors.Red);
}
}
}
}
if(e.OldItems != null)
{
foreach(SortDescription sortDesc in e.OldItems)
{
foreach(var column in AssociatedObject.Columns)
{
var boundColumn = column as DataGridBoundColumn;
if (boundColumn == null)
continue;
if (boundColumn.Binding.Path.Path == sortDesc.PropertyName)
{
foreach (var row in rows)
ColorCell(column,row,Colors.White);
}
}
}
}
}
private void ColorCell(DataGridColumn column, DataGridRow item, Color color)
{
var content = column.GetCellContent(item);
if (content == null)
return;
var parent = GetParent<DataGridCell>(content);
if (parent != null)
parent.Background = new SolidColorBrush(color);
}
public static T GetParent<T>(DependencyObject source)
where T : DependencyObject
{
DependencyObject parent = VisualTreeHelper.GetParent(source);
while (parent != null && !typeof(T).IsAssignableFrom(parent.GetType()))
{
parent = VisualTreeHelper.GetParent(parent);
}
return (T)parent;
}
}
那近乎完美的作品。非常感谢您的回答,我注意到的唯一一件事情是它有时会出现滚动问题,但它仍然是一个非常大的帮助! – GotDibbs 2010-10-19 18:49:29
滚动问题是由'DataGrid'虚拟化行的方式引起的。它只是实例化屏幕上可见的行数加1并将其保存在内存中。要解决此问题,您可能需要修改代码以保留已排序的列的列表,并在加载行事件处理程序中突出显示这些列的单元格。 – Stephan 2010-10-19 19:02:10
Yeap这是我采取的确切路线。再次感谢! – GotDibbs 2010-10-19 19:20:33