Visual Studio 如何在WPF C#中获取dataGrid中单元格的大小和位置

qgzx9mmu  于 2023-11-21  发布在  C#
关注(0)|答案(2)|浏览(233)

我已经开始在WPF中使用dataGrid,但是来自WinForm,它与我习惯的有点不同。
我现在的问题是,我需要得到一个特定的单元格的矩形(这样我就可以访问它的大小和位置)。
在WinForm的datagrid中,有一个方法称为:

  1. cellRectangle = dataGridView.GetCellDisplayRectangle(columnIndex, rowIndex, cutOverflow)

字符串
然而,我似乎在WPF中找不到这样的东西,与我过去在WinForm中所能做的相比,我在网上能找到的一切都非常复杂。
如果可能的话,我希望避免使用任何XAML代码,并全部使用C#代码编写
希望你们中有人能解决我的问题。

rfbsl7qr

rfbsl7qr1#

WPF不适用于坐标,而是容器。如果您想将某些内容放入DataGridCell中,请找到它并将新内容放入DataGridCell.Content中。
在我的示例中,您可以输入行号和列号,然后按执行代码按钮。这将在网格中的所需位置放置一个按钮。单击单击我后,按钮消失,显示旧单元格内容。


的数据

  1. <Window x:Class="DataGridCell.MainWindow"
  2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  5. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  6. xmlns:local="clr-namespace:DataGridCell"
  7. mc:Ignorable="d"
  8. Title="MainWindow" Height="450" Width="800">
  9. <DockPanel>
  10. <StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Background="LightGray">
  11. <Label Content="Row:"/>
  12. <TextBox Name="RowTextBox" Text="2"/>
  13. <Label Content="Column:"/>
  14. <TextBox Name="ColumnTextBox" Text="1"/>
  15. <Button DockPanel.Dock="Bottom" Content="Execute Code" Name="ExecuteButton"/>
  16. </StackPanel>
  17. <DataGrid Name="MainDataGrid" ItemsSource="{Binding}" AutoGenerateColumns="False" >
  18. <DataGrid.Columns>
  19. <DataGridTextColumn Header="Col0" Binding="{Binding Col0}"/>
  20. <DataGridTextColumn Header="Col1" Binding="{Binding Col1}" />
  21. <DataGridTextColumn Header="Col2" Binding="{Binding Col2}" />
  22. </DataGrid.Columns>
  23. </DataGrid>
  24. </DockPanel>
  25. </Window>
  26. using System.Collections.Generic;
  27. using System.Collections.ObjectModel;
  28. using System.Windows;
  29. using System.Windows.Controls;
  30. namespace DataGridCell {
  31. public class RowData {
  32. public string Col0 { get; set; }
  33. public string Col1 { get; set; }
  34. public string Col2 { get; set; }
  35. }
  36. public partial class MainWindow: Window {
  37. public MainWindow() {
  38. InitializeComponent();
  39. var dataList = new List<RowData>();
  40. dataList.Add(new RowData {Col0="0.0", Col1="0.1", Col2="0.2"});
  41. dataList.Add(new RowData {Col0="1.0", Col1="1.1", Col2="1.2"});
  42. dataList.Add(new RowData {Col0="2.0", Col1="2.1", Col2="2.2"});
  43. dataList.Add(new RowData {Col0="3.0", Col1="3.1", Col2="3.2"});
  44. ObservableCollection<RowData> custdata = new ObservableCollection<RowData>(dataList);
  45. MainDataGrid.DataContext = custdata;
  46. ExecuteButton.Click+=ExecuteButton_Click;
  47. }
  48. ContentControl cell;
  49. object oldContent;
  50. private void ExecuteButton_Click(object sender, RoutedEventArgs e) {
  51. var row = int.Parse(RowTextBox.Text);
  52. var col = int.Parse(ColumnTextBox.Text);
  53. var cellContent = (FrameworkElement)MainDataGrid.Columns[col].GetCellContent(MainDataGrid.Items[row]);
  54. cell = (ContentControl)cellContent.Parent;
  55. var button = new Button {Content="Click me" };
  56. button.Click += Button_Click;
  57. oldContent = cell.Content;
  58. cell.Content = button;
  59. ExecuteButton.IsEnabled = false;
  60. }
  61. private void Button_Click(object sender, RoutedEventArgs e) {
  62. cell.Content = oldContent;
  63. ExecuteButton.IsEnabled = true;
  64. }
  65. }
  66. }

字符串
虽然这样做是可行的,但它有点像黑客。如果数据网格重新创建它的内容,你的按钮将丢失。例如,如果用户单击列标题来对网格进行排序,就会发生这种情况。
如果你真的需要单元格的尺寸,你可以用cell.ActualWidth和cell.ActualHeight来获取。但是这些值可能随时改变,例如当用户改变列的宽度时。坐标在WPF中不使用。如果你需要定义控件的确切位置,使用它的Margin来定位它。

展开查看全部
x8goxv8g

x8goxv8g2#

获取单元格的中心:(当这个解决方案与winforms one相比复杂得可笑时,微软为你感到羞耻)

  1. public Point GetCenterPointOfCell(int rowId_0Based, int colId_0Based)
  2. {
  3. Point ret = Point.Empty;
  4. _grid.Dispatcher.Invoke(new Action(() =>
  5. {
  6. var item = _grid.Items[rowId_0Based];
  7. int currentRow = _grid.SelectedIndex == -1 ? 0 : _grid.SelectedIndex;
  8. System.Windows.DependencyObject dep = _grid.ItemContainerGenerator.ContainerFromIndex(currentRow);
  9. var dataGridRow = dep as DataGridRow;
  10. if (dataGridRow is null)
  11. {
  12. string msg = $"Cannot acces row[{currentRow}] of datagrid";
  13. _log.Error(msg);
  14. throw new AccessViolationException(msg);
  15. }
  16. int visibleRowCount = (int)(_grid.ActualHeight / dataGridRow.ActualHeight * 0.8);
  17. if (rowId_0Based > _grid.SelectedIndex + visibleRowCount || rowId_0Based < _grid.SelectedIndex)
  18. {
  19. object targetScroll;
  20. if (rowId_0Based + visibleRowCount<_grid.Items.Count)
  21. {
  22. targetScroll = _grid.Items[rowId_0Based + visibleRowCount];
  23. }
  24. else
  25. {
  26. targetScroll = item;
  27. }
  28. _grid.ScrollIntoView(targetScroll);
  29. _grid.UpdateLayout();
  30. }
  31. var cellContentElement = _grid.Columns[colId_0Based].GetCellContent(item);
  32. if (cellContentElement == null)
  33. throw new Exception("cannot get cell content");
  34. System.Windows.Rect cellBounds = cellContentElement.TransformToAncestor(_grid).TransformBounds(new System.Windows.Rect(0, 0, cellContentElement.ActualWidth, cellContentElement.ActualHeight));
  35. var centerPoint = new System.Windows.Point((int)(cellBounds.X + cellBounds.Width / 2), (int)(cellBounds.Y + cellBounds.Height / 2));
  36. System.Windows.Point winPoint = _grid.PointToScreen(centerPoint);
  37. ret = new Point((int)winPoint.X, (int)winPoint.Y);
  38. }));
  39. return ret;
  40. }

字符串

展开查看全部

相关问题