如何通过列和行索引获取WPF网格中单元格的x,y坐标

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何通过列和行索引获取WPF网格中单元格的x,y坐标相关的知识,希望对你有一定的参考价值。

我有一个网格,我在那里以progamatic方式添加rowdefinitions和col定义。

<Grid>
    <Grid Name="layoutGrid" ></Grid>
    <Canvas Name="overlayedCanvas"></Canvas>
</Grid>

.

// create rows
for (int r = 0; r < rowCount; r++)
    layoutGrid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto});
// create columns
for (int c = 0; c < colCount; c++)
    layoutGrid.ColumnDefinitions.Add(new ColumnDefinition {Width = GridLength.Auto});

然后我将用户控件放在一些单元格中。网格根据各个用户控件大小进行自动调整大小。

我的目标是绘制连接一些单元格的多边形。例如它可以是从单元格[1,1]的左上角开始直到细胞[3,3]右下角的Rect(1,1,3,3)。我正在考虑使用这种方法access children by x,y coordinates但我必须在每个单元格内创建虚拟控件。

然后我可以计算单元格位置:

Point topLeft = uc.TranslatePoint(new Point(0,0), layoutGrid);
Point bottomRight = uc.TranslatePoint(new Point(uc.ActualWidth, uc.ActualHeight), layoutGrid);

有没有更好的方法呢?

谢谢

答案
public partial class MainWindow : Window
{
    private delegate void LoadDelegate();

    public MainWindow()
    {
        InitializeComponent();

        LoadDelegate oD = Load;
        Dispatcher.BeginInvoke (
            oD,  
            System.Windows.Threading.DispatcherPriority.Loaded, 
            null
        );
    }

    private void Load()
    {
        var items = LogicalTreeHelper
                        .GetChildren(uiGrid)
                        .OfType<Border>()
                        .Select(brd => new { Column = Grid.GetColumn(brd), Row = Grid.GetRow(brd), Item = brd })
                        .ToList();
        Border oStart = items
                            .FirstOrDefault(item => item.Column == 1 && item.Row == 1)
                            .Item;
        Border oStop = items
                            .FirstOrDefault(item => item.Column == 2 && item.Row == 2)
                            .Item;

        Point topLeft = oStart.PointToScreen(new Point(0, 0));
        Point bottomRight = oStop.PointToScreen(new Point(oStop.ActualWidth, oStop.ActualHeight));

        Rectangle oRect = new Rectangle();
        oRect.Fill = new SolidColorBrush(Color.FromRgb(0, 255, 0));

        Point oLeft = uiCanvas.PointFromScreen(topLeft);
        Canvas.SetLeft(oRect, oLeft.X);
        Canvas.SetTop(oRect, oLeft.Y);
        oRect.Width = bottomRight.X - topLeft.X;
        oRect.Height = bottomRight.Y - topLeft.Y;

        uiCanvas.Children.Add(oRect);
    }
}

...

<Grid>
    <Grid x:Name="uiGrid">
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>

        <Border Background="Red" Grid.Column="1" Grid.Row="1" />
        <Border Background="Red" Grid.Column="2" Grid.Row="2" />
    </Grid>

    <Canvas x:Name="uiCanvas" />
</Grid>
另一答案

获取WPF Rect[ , ]中所有单元格的Grid维度:

返回WPF Grid中所有单元格的当前运行时维度,由RowDefinition.​ActualHeightColumnDefinition.ActualWidth报告。结果以二维数组Rect[row,column]返回。例如,返回数组中最后一个元素的PointRect.BottomRight将等于调用时RenderSizeGrid

public static Rect[,] GetCellRects(this Grid grid) =>
                      GetCellRects(grid.RowDefinitions, grid.ColumnDefinitions);

static Rect[,] GetCellRects(RowDefinitionCollection rows, ColumnDefinitionCollection cols)
{
    int i = rows.Count, j = cols.Count;
    var a = new Rect[i, j];
    if (i > 0 && j > 0)
    {
        Double x;
        for (i = a.GetLength(0); --i >= 0;)
            for (x = rows[i].ActualHeight, j = a.GetLength(1); --j >= 0;)
                a[i, j].Height = x;

        for (j = a.GetLength(1); --j >= 0;)
            for (x = cols[j].ActualWidth, i = a.GetLength(0); --i >= 0;)
                a[i, j].Width = x;

        for (i = 0; i < a.GetLength(0); i++)
            for (j = 0; j < a.GetLength(1); j++)
            {
                if (j > 0)
                    a[i, j].X = a[i, j - 1].Right;
                if (i > 0)
                    a[i, j].Y = a[i - 1, j].Bottom;
            }
    }
    return a;
}

顺便说一下,这段代码采用了经典的Dynamic Programming规范示例之一。这里的好处是每个ActualHeightActualWidth属性每行或每列只能访问一次,这个数字显然是最小的。尝试设计此处显示的代码的替代方案来保留该行为是一种有趣的练习。或者相反,说服自己为什么最终的嵌套循环不能反向进行,就像之前的循环那样......?

以上是关于如何通过列和行索引获取WPF网格中单元格的x,y坐标的主要内容,如果未能解决你的问题,请参考以下文章

WPF 数据网格性能

如何将总和添加到表中并获取 R 中每个单元格的比例

如何获取excel表格中占用单元格的范围

如何在我的 DataGrid 中获取所选单元格的当前列(C# WPF 应用程序)

如何在基于部分的表格视图中获取开关更改事件中单元格的索引路径

根据纬度和经度获取网格中单元格的位置