Wpf Datagrid 操作总结
1. 行选中时,.SelectedIndex可以获取行索引,多行选中可用 SelectedItems
2.单元格选中时,获取行索引可以用以下(Grid为DataGrid的对象)
DataGridCellInfo selectedCell = Grid.SelectedCells.FirstOrDefault(); //没有选中Record if (selectedCell == null || selectedCell.Column == null) return; int index = Grid.Items.IndexOf(selectedCell.Item);
3.替换某个单元格中TextBlock为Combox
DataGridRow row = (DataGridRow)Grid.ItemContainerGenerator.ContainerFromIndex(Index); DataGridCellsPresenter presenter = GetVisualChild<DataGridCellsPresenter>(row); //这行代码是通过行得到单元格 DataGridCell cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(Col); //这行代码是通过index得到具体的单元格 FrameworkElementFactory factory = new FrameworkElementFactory(typeof(StackPanel), "StackPanelName"); factory.SetValue(StackPanel.OrientationProperty, Orientation.Horizontal); FrameworkElementFactory buttonComboBox = new FrameworkElementFactory(typeof(ComboBox), "ComboxName"); buttonComboBox.SetValue(ComboBox.SelectedIndexProperty, 0); buttonComboBox.SetValue(ComboBox.DisplayMemberPathProperty, "Data"); buttonComboBox.SetValue(ComboBox.ItemsSourceProperty, filterDataList); buttonComboBox.SetValue(ComboBox.WidthProperty, cell.ActualWidth); buttonComboBox.SetValue(ComboBox.FontSizeProperty, cell.FontSize - 3); buttonComboBox.AddHandler( ComboBox.LoadedEvent, new RoutedEventHandler( (s, ea) => { ComboBox comboBox = (ComboBox)s; comboBox.DropDownClosed += ComboBox_DropDownClosed; })); factory.AppendChild(buttonComboBox); DataTemplate dataTemplate = new DataTemplate(); dataTemplate.VisualTree = factory; if(cell.ContentTemplate == null) { cell.ContentTemplate = dataTemplate; //获取元素,并设置焦点 ContentPresenter myContentPresenter = FindVisualChild<ContentPresenter>(cell); bool ret = myContentPresenter.ApplyTemplate(); DataTemplate myDataTemplate = myContentPresenter.ContentTemplate; ComboBox myCombox = (ComboBox)myDataTemplate.FindName("ComboxName", myContentPresenter); myCombox.Focus(); }
private childItem FindVisualChild<childItem>(DependencyObject obj) where childItem : DependencyObject { for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++) { DependencyObject child = VisualTreeHelper.GetChild(obj, i); if (child != null && child is childItem) return (childItem)child; else { childItem childOfChild = FindVisualChild<childItem>(child); if (childOfChild != null) return childOfChild; } } return null; }
4. ItemContainerGenerator顺序为Datagrid显示的顺序,排序后也与之对应
5.如果用FrameworkElementFactory生成Datagrid列,但是没有用ApplyTemplate(), 在用myDataTemplate.FindName是找不到的,可以用
DataGridTemplateColumn templeColumn = Grid_Holes.Columns[displayIndex] as DataGridTemplateColumn;
if (templeColumn == null) return;
templeColumn.CellTemplate.LoadContent();
进行查找
6.Datagrid 已知行列,获取DataGridCell
DataGridCell dataGridCell = GetDataGridCellWithScroll(dataGrid, row, column);
/// <summary> /// 获取指定的单元格时是否允许滚动 /// </summary> /// <param name="dataGrid">DataGrid对象</param> /// <param name="rowIndex">行索引</param> /// <param name="columnIndex">列索引</param> /// <param name="needScroll">不在可见范围内是否允许滚动查找</param> /// <returns></returns> public static DataGridCell GetDataGridCellWithScroll(DataGrid dataGrid, int rowIndex, int columnIndex, bool needScroll = false) { try { DataGridRow rowContainer = GetDataGridRow(dataGrid, rowIndex, needScroll); if (rowContainer != null) { DataGridCellsPresenter presenter = GetVisualChild<DataGridCellsPresenter>(rowContainer); //这行代码是通过行得到单元格 DataGridCell cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(columnIndex); //这行代码是通过index得到具体的单元格 if (cell == null) { if (needScroll) { dataGrid.ScrollIntoView(rowContainer, dataGrid.Columns[columnIndex]); cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(columnIndex); } } return cell; } } catch { return null; } return new DataGridCell(); } public static DataGridRow GetDataGridRow(DataGrid dataGrid, int index, bool needScroll = false) { if (index >= dataGrid.Items.Count) { throw new IndexOutOfRangeException(String.Format("Index {0} is out of range.", index)); } DataGridRow row = (DataGridRow)dataGrid.ItemContainerGenerator.ContainerFromIndex(index); if (row == null) { if (needScroll) { // may be virtualized, bring into view and try again dataGrid.ScrollIntoView(dataGrid.Items[index]); WaitFor(TimeSpan.Zero, DispatcherPriority.SystemIdle); row = (DataGridRow)dataGrid.ItemContainerGenerator.ContainerFromIndex(index); } } return row; } public static void WaitFor(TimeSpan time, DispatcherPriority priority) { DispatcherTimer timer = new DispatcherTimer(priority); timer.Tick += new EventHandler(OnDispatched); timer.Interval = time; DispatcherFrame dispatcherFrame = new DispatcherFrame(false); timer.Tag = dispatcherFrame; timer.Start(); Dispatcher.PushFrame(dispatcherFrame); } public static void OnDispatched(object sender, EventArgs args) { DispatcherTimer timer = (DispatcherTimer)sender; timer.Tick -= new EventHandler(OnDispatched); timer.Stop(); DispatcherFrame frame = (DispatcherFrame)timer.Tag; frame.Continue = false; } public static T GetVisualChild<T>(Visual parent) where T : Visual { T childContent = default(T); int numVisuals = VisualTreeHelper.GetChildrenCount(parent); for (int i = 0; i < numVisuals; i++) { Visual v = (Visual)VisualTreeHelper.GetChild(parent, i); childContent = v as T; if (childContent == null) { childContent = GetVisualChild<T>(v); } if (childContent != null) { break; } } return childContent; } public static List<T> GetChildObjects<T>(DependencyObject obj, string name) where T : FrameworkElement { DependencyObject child = null; List<T> childList = new List<T>(); for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++) { child = VisualTreeHelper.GetChild(obj, i); if (child is T && (((T)child).Name == name | string.IsNullOrEmpty(name))) { childList.Add((T)child); } childList.AddRange(GetChildObjects<T>(child, name)); } return childList; } public static T GetChildObject<T>(DependencyObject parentObj, string name) where T : FrameworkElement { DependencyObject child = null; T grandChild = null; for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parentObj); i++) { child = VisualTreeHelper.GetChild(parentObj, i); if (child is T && (((T)child).Name == name | string.IsNullOrEmpty(name))) { return (T)child; } else { grandChild = GetChildObject<T>(child, name); if (grandChild != null) return grandChild; } } return null; }
7.已知DataGridRow,获取行号
public static int FindRowIndex(DataGridRow row) { DataGrid dataGrid = ItemsControl.ItemsControlFromItemContainer(row) as DataGrid; int index = dataGrid.ItemContainerGenerator.IndexFromContainer(row); return index; }
8.由DataGridCell 获取TextBlock
TextBlock textBlock = (dataGrid.Columns[column].GetCellContent(dataGrid.Items[row]) as TextBlock);
TextBlock tb = GetVisualChild<TextBlock>(dataGridCell);