WPF 4 DataGrid:将行号放入 RowHeader [英] WPF 4 DataGrid: Getting the Row Number into the RowHeader
问题描述
我希望将行号放入 WPF 4 DataGrid 的 RowHeader 中,以便它有一个类似于 Excel 的列用于 DataGrid 的行号.
I am looking to get the row number into the RowHeader of the WPF 4 DataGrid so it has an Excel-like column for the row numbers of the DataGrid.
我在网上看到的解决方案建议向业务对象添加索引字段.这不是一个真正的选择,因为 DataGrid 将被大量使用,我们不希望必须不断跟踪更改这些索引字段.
The solution I've seen out there on the web suggests adding an index field to the business objects. This isn't really an option because the DataGrid will be getting resorted a lot and we don't want to have to keep track of changing these index fields constantly.
非常感谢
推荐答案
一种方法是将它们添加到 DataGrid
的 LoadingRow 事件中.
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();
}
更新
要使其与 WPF Toolkit 中的 .NET 3.5 DataGrid 一起使用,需要进行一些修改.索引仍能正确生成,但在使用虚拟化时输出失败.对 RowHeaderTemplate
的以下修改修复了这个问题
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>
编辑 2012-07-05
如果从源列表中添加或删除项目,则数字将不同步,直到列表滚动,以便再次调用 LoadingRow
.解决这个问题有点复杂,我现在能想到的最佳解决方案是保留上面的 LoadingRow
解决方案,并且
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
- 订阅
dataGrid.ItemContainerGenerator.ItemsChanged
- 在事件处理程序中,找到可视化树中的所有子
DataGridRows
- 将Header设置为每个
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
}
这篇关于WPF 4 DataGrid:将行号放入 RowHeader的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!