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

问题描述 投票:1回答:2

我有一个网格,我在那里以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);

有没有更好的方法呢?

谢谢

c# wpf wpf-controls grid
2个回答
0
投票
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>

0
投票

获取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属性每行或每列只能访问一次,这个数字显然是最小的。尝试设计此处显示的代码的替代方案来保留该行为是一种有趣的练习。或者相反,说服自己为什么最终的嵌套循环不能反向进行,就像之前的循环那样......?

© www.soinside.com 2019 - 2024. All rights reserved.