One way is to add them in the LoadingRow event for the DataGrid
.
<DataGrid Name="DataGrid" LoadingRow="DataGrid_LoadingRow" ... />
void DataGrid_LoadingRow(object sender, DataGridRowEventArgs e)
{
// Adding 1 to make the row count start at 1 instead of 0
// as pointed out by daub815
e.Row.Header = (e.Row.GetIndex() + 1).ToString();
}
Update
To get this to work with the .NET 3.5 DataGrid in WPF Toolkit a little modification is needed. The index is still generated correctly but the output fails when using virtualization. The following modification to the RowHeaderTemplate
fixes this
<toolkit:DataGrid LoadingRow="DataGrid_LoadingRow">
<toolkit:DataGrid.RowHeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type toolkit:DataGridRow}},
Path=Header}"/>
</DataTemplate>
</toolkit:DataGrid.RowHeaderTemplate>
</toolkit:DataGrid>
Edit 2012-07-05
If items are added or removed from the source list then the numbers get out of sync until the list is scrolled so LoadingRow
is called again. Working around this issue is a little more complex and the best solution I can think of right now is to keep the LoadingRow
solution above and also
- Subscribe to
dataGrid.ItemContainerGenerator.ItemsChanged
- In the event handler, find all the child
DataGridRows
in the visual tree
- Set the Header to the index for each
DataGridRow
Here is an attached behavior which does this. Use it like this
<DataGrid ItemsSource="{Binding ...}"
behaviors:DataGridBehavior.DisplayRowNumber="True">
DisplayRowNumber
public class DataGridBehavior
{
#region DisplayRowNumber
public static DependencyProperty DisplayRowNumberProperty =
DependencyProperty.RegisterAttached("DisplayRowNumber",
typeof(bool),
typeof(DataGridBehavior),
new FrameworkPropertyMetadata(false, OnDisplayRowNumberChanged));
public static bool GetDisplayRowNumber(DependencyObject target)
{
return (bool)target.GetValue(DisplayRowNumberProperty);
}
public static void SetDisplayRowNumber(DependencyObject target, bool value)
{
target.SetValue(DisplayRowNumberProperty, value);
}
private static void OnDisplayRowNumberChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
{
DataGrid dataGrid = target as DataGrid;
if ((bool)e.NewValue == true)
{
EventHandler<DataGridRowEventArgs> loadedRowHandler = null;
loadedRowHandler = (object sender, DataGridRowEventArgs ea) =>
{
if (GetDisplayRowNumber(dataGrid) == false)
{
dataGrid.LoadingRow -= loadedRowHandler;
return;
}
ea.Row.Header = ea.Row.GetIndex();
};
dataGrid.LoadingRow += loadedRowHandler;
ItemsChangedEventHandler itemsChangedHandler = null;
itemsChangedHandler = (object sender, ItemsChangedEventArgs ea) =>
{
if (GetDisplayRowNumber(dataGrid) == false)
{
dataGrid.ItemContainerGenerator.ItemsChanged -= itemsChangedHandler;
return;
}
GetVisualChildCollection<DataGridRow>(dataGrid).
ForEach(d => d.Header = d.GetIndex());
};
dataGrid.ItemContainerGenerator.ItemsChanged += itemsChangedHandler;
}
}
#endregion // DisplayRowNumber
#region Get Visuals
private static List<T> GetVisualChildCollection<T>(object parent) where T : Visual
{
List<T> visualCollection = new List<T>();
GetVisualChildCollection(parent as DependencyObject, visualCollection);
return visualCollection;
}
private static void GetVisualChildCollection<T>(DependencyObject parent, List<T> visualCollection) where T : Visual
{
int count = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < count; i++)
{
DependencyObject child = VisualTreeHelper.GetChild(parent, i);
if (child is T)
{
visualCollection.Add(child as T);
}
if (child != null)
{
GetVisualChildCollection(child, visualCollection);
}
}
}
#endregion // Get Visuals
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…