如何动态地在画布中放置按钮以使它们不会相互重叠?

时间:2015-05-11 09:34:46

标签: c# .net wpf canvas windows-phone-8.1

我正在用C#,WPF,Windows Phone 8.1应用程序编写应用程序,我在480x480矩形网格中有一个画布,我想根据某些逻辑将一些按钮放到画布上,最少有5个按钮和最多12-15个按钮,现在基于某些条件我想在画布中放置按钮,使它不会相互重叠。

我开始使用Grid构思,最初设置行数和列数,每行/列只有一个按钮,假设我有6个按钮,我将调用此方法CreateButtonsControls(3,3);,但它将按钮放在里面的方式它对我来说看起来非常单调。

private void CreateButtonsControls(int rows, int columns)
    {
        // Create a Grid
        Grid rootGrid = new Grid();

        // It will create columns
        createColumns(rootGrid, columns);

        // It will create rows
        createRow(rootGrid, rows);

        for (int i = 0; i < rows; i++)
        {
            for (int j = 0; j < columns; j++)
            {
                Button button = new Button();
                button.HorizontalAlignment = HorizontalAlignment.Right;
                button.VerticalAlignment = VerticalAlignment.Top;
                button.Margin = new Thickness(3);
                button.Width = 50;
                button.Height = 50;
                button.Content = "12";
                Grid.SetRow(button, i);
                Grid.SetColumn(button, j);
                rootGrid.Children.Add(button);
            }
        }
        // This will add the root grid to UI
        grdButton.Children.Add(rootGrid);

    }

我想在画布上实现它。我希望所有按钮都放在画布分散方式中。但我不知道如何实现这一目标。

有一个属性
Canvas.SetLeft(UIControl, positionX ) Canvas.SetTop(UIControl, positionY )

但是我如何在运行时决定这个positionX和positionY,以便它不会相互重叠,任何想法或建议?

由于

1 个答案:

答案 0 :(得分:1)

你可以做这样的事情,首先,在你的标记中假设一个名为MyCanvas的画布:

<Canvas Name="MyCanvas" Loaded="MyCanvas_Loaded">        
</Canvas>

然后是一个帮助类,它允许我们检查按钮是否与另一个按钮重叠:

class ButtonPosition {
    public int TopLeftX { get; set; }
    public int TopLeftY { get; set; }
    public int BottomRightX {
        get { return TopLeftX + Width; }
    }
    public int BottomRightY {
        get { return TopLeftY + Height; }
    }
    public int Width { get; set; }
    public int Height { get; set; }

    public ButtonPosition(int topLeftX, int topLeftY, int width, int height) {
        TopLeftX = topLeftX;
        TopLeftY = topLeftY;
        Width = width;
        Height = height;
    }

    public bool Overlaps(ButtonPosition bp) {
        return (bp.TopLeftX < this.BottomRightX && bp.BottomRightX > this.TopLeftX && bp.TopLeftY < this.BottomRightY && bp.BottomRightY > this.TopLeftY);
    }
}

然后,当画布加载时:

private void MyCanvas_Loaded(object sender, RoutedEventArgs e) {
    int numButtons = 20;
    int buttonWidth = 50;
    int buttonHeight = 50;

    Random r = new Random();
    // Keep track of the buttons as we add them to the canvas
    List<ButtonPosition> buttonPositions = new List<ButtonPosition>();

    for (int i = 0; i < numButtons; i++) {
        Button button = new Button();
        button.HorizontalAlignment = HorizontalAlignment.Right;
        button.VerticalAlignment = VerticalAlignment.Top;
        button.Margin = new Thickness(3);
        button.Width = buttonWidth;
        button.Height = buttonHeight;
        button.Content = i.ToString();
        bool foundOverlap = false;
        int left;
        int top;
        ButtonPosition bp;  
        do {
            foundOverlap = false;
            // Create a new random position for the button (subtracting the width/height from the X,Y so that we don't overlap the edge of the canvas)
            left = r.Next(0, (int)MyCanvas.ActualWidth - buttonWidth);
            top = r.Next(0, (int)MyCanvas.ActualHeight - buttonHeight);
            bp = new ButtonPosition(left, top, buttonWidth, buttonHeight);
            // Check each of the existing buttons for overlap
            foreach (ButtonPosition existingButton in buttonPositions) {
                if (bp.Overlaps(existingButton)) {
                    foundOverlap = true;
                    break;
                }
            }
        } while (foundOverlap);

        // Add the verified button to the canvas
        MyCanvas.Children.Add(button);
        Canvas.SetLeft(button, left);
        Canvas.SetTop(button, top);
        // Add the position of the button to our collection
        buttonPositions.Add(bp);
    }
}

这绝不是一个完美的解决方案,因为while循环效率低下。在找到一个没有重叠按钮之前,它可能会出现许多重叠的按钮。如果向画布添加更多按钮,这显然会变得更糟。此外,如果您尝试添加的按钮多于适合的尺寸,那么当它为按钮寻找空间时,您将陷入无限循环!