我试图以编程方式选择
WPF DataGrid中的整个列.我的代码似乎工作,但它真的很慢!我猜这是因为它不断调用ScrollIntoView.有人可以帮助我找到加速它的解决方案或选择整个列的替代方案吗?
public static void SelectColumn(DataGrid grid,int column) { for (int i = 0; i < grid.Items.Count; i++) { // Select each cell in this column var cell = DataGridHelper.GetCell(grid,i,column); if (cell != null) { cell.IsSelected = true; } } DataGridHelper.GetCell(grid,column).Focus(); } public static DataGridCell GetCell(DataGrid grid,int row,int column) { DataGridRow rowContainer = GetRow(grid,row); if (rowContainer != null) { DataGridCellsPresenter presenter = TreeHelper.GetVisualChild<DataGridCellsPresenter>(rowContainer); if (presenter == null) { // may be virtualized,bring into view and try again grid.ScrollIntoView(rowContainer,grid.Columns[column]); presenter = TreeHelper.GetVisualChild<DataGridCellsPresenter>(rowContainer); } if (presenter != null) { // try to get the cell but it may possibly be virtualized DataGridCell cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(column); if (cell == null) { // may be virtualized,bring into view and try again grid.ScrollIntoView(rowContainer,grid.Columns[column]); cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(column); } return cell; } } return null; } public static DataGridRow GetRow(DataGrid grid,int index) { DataGridRow row = (DataGridRow)grid.ItemContainerGenerator.ContainerFromIndex(index); if (row == null) { // may be virtualized,bring into view and try again grid.ScrollIntoView(grid.Items[index]); row = (DataGridRow)grid.ItemContainerGenerator.ContainerFromIndex(index); } return row; }
更新:
我正在尝试@ianschol建议的解决方案.这就是我所拥有的(我在b / c后面的代码中绑定我不知道在运行时需要多少列):
for (int i = 0; i < this.CurrentData.Data[0].Length; i++) { TheGrid.Columns.Add( new DataGridTextColumn { Header = (this.CurrentData.Rank > 1) ? string.Format(this.culture,headerFormatString,i + 1) : string.Empty,Binding = new Binding(string.Format("[{0}].DataValue",i)) { ValidatesOnDataErrors = true,UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged },Width = DataGridLength.Auto,ElementStyle = new Style { targettype = typeof(TextBlock),Triggers = { this.errorTrigger } },EditingElementStyle = new Style { targettype = typeof(TextBox),CellStyle = new Style { targettype = typeof(DataGridCell),Setters = { new Setter { Property = DataGridCell.IsSelectedProperty,Value = new Binding(string.Format("[{0}].IsSelected",i)) { Mode = BindingMode.TwoWay,} },} }); }
和我的IsSelected财产:
private bool isSelected = false; public bool IsSelected { get { return this.isSelected; } set { this.isSelected = value; OnPropertyChanged("IsSelected"); } }
而新的SelectColumn代码:
public static void SelectColumn(DataGrid grid,int column) { for (int i = 0; i < grid.Items.Count; i++) { // Select each cell in this column ((DataItem[])(grid.Items[i]))[column].IsSelected = true; } }
问题是,如果我在代码中更新IsSelected属性,它会更新GUI(有点,它古怪),但反之亦然.即如果我在GUI中选择一个单元格/行,它不会在代码中调用属性设置器.你可以看到绑定是TwoWay所以我不确定这个问题.
另一个更新:问题似乎与虚拟化有关.如果我关闭虚拟化(VirtualizingStackPanel.IsVirtualizing =“False”),它可以正常工作.
解决方法
一种更有效的方法可能是在DataSource的类上使用IsSelected属性,这样每列都有一个相应的“IsSelected”属性.
public class MyData : INotifyPropertyChanged { private string name; public string Name { get { return name; } set { name = value; Notify("Name"); } } private bool nameSelected = false; public bool NameSelected { get { return nameSelected; } set { nameSelected = value; Notify("NameSelected"); } } //... etc ... }
接下来,您可以更改每个Column的CellStyle,以将单元格的IsSelected属性绑定到类上的相关IsSelected属性.
<DataGrid ItemsSource="{Binding Users}" AutoGenerateColumns="False" HorizontalAlignment="Left" Name="scratchGrid" CanUserAddRows="False" VerticalScrollBarVisibility="Auto" SelectionUnit="Cell"> <DataGrid.Columns> <DataGridTextColumn Binding="{Binding Name}" Header="User Name" Width="200"> <DataGridTextColumn.CellStyle> <Style targettype="{x:Type DataGridCell}"> <Setter Property="IsSelected" Value="{Binding NameSelected}" /> </Style> </DataGridTextColumn.CellStyle> </DataGridTextColumn> <DataGridTextColumn Binding="{Binding Age}" Header="User Age" Width="80"> <DataGridTextColumn.CellStyle> <Style targettype="{x:Type DataGridCell}"> <Setter Property="IsSelected" Value="{Binding AgeSelected}" /> </Style> </DataGridTextColumn.CellStyle> </DataGridTextColumn> </DataGrid.Columns> </DataGrid>
最后,像这样实现你的select-all代码(这会在Age上选择all,你可能希望做一个更通用/更优雅的实现;)):
foreach (MyData user in Users) { user.AgeSelected = true; }
您必须注意确保所有NotifyPropertyChanged行为都排成一行,因为您希望网格能够识别其绑定集合中的属性正在更新.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。