1

我是 WPF 的新手。我在按钮单击时在画布上一个接一个地添加矩形。当我从 TextBox 设置特定矩形的高度时。它与子矩形重叠。

例如:。 当有 3 个矩形时Height=100Width=200& 当我设置高度为Second Rectangle to 150. 那么孩子Rectangle必须出现在第二个矩形之后并且不能在第三个矩形上重叠。可能吗?

static int val=0;
List<UIElement> itemstoremove = new List<UIElement>();
private void BtnAdd_Click(object sender, RoutedEventArgs e)
        {

            int heigt = 0;
            int wegt = 0;
             if (!string.IsNullOrEmpty(txtHeight.Text) && !string.IsNullOrEmpty(txtWidth.Text))
            {
                heigt = int.Parse(txtHeight.Text);
                wegt = int.Parse(txtWidth.Text);
            }
            rect = new Rectangle();
            rect.Stroke = Brushes.Red;
            rect.StrokeThickness = 2;
            rect.Height = heigt;
            rect.Width = wegt;
            Canvas.SetLeft(rect, 10);
            Canvas.SetTop(rect, (rect.Height) * val);
            rect.Tag = val;
            canvasboard.Children.Add(rect);
            val = val + 1;
            //canvasboard is Canvas object
            foreach (UIElement ui in canvasboard.Children)
            {
                if (ui.GetType() == typeof(Rectangle))
                {
                    itemstoremove.Add(ui);
                }
            }
        }

修改高度和宽度:

private void BtnModify_Click(object sender, RoutedEventArgs e)
        {
            int heigt = 0;
            int wegt = 0;
            if (!string.IsNullOrEmpty(txtHeight.Text) && !string.IsNullOrEmpty(txtWidth.Text))
            {
                heigt = int.Parse(txtHeight.Text);
                wegt = int.Parse(txtWidth.Text);
            }
            Rectangle rectToRemove;

            foreach (UIElement ui in itemstoremove)
            {
                if (ui.GetType() == typeof(Rectangle) && ((Rectangle)ui).Tag.ToString() == txtModifyRect.Text)
                {
                    rectToRemove = ui as Rectangle;
                    //itemstoremove.Remove(rectToRemove);
                    rectToRemove.Height = heigt;
                    rectToRemove.Width = wegt;
                    //canvasboard.Children.Remove(rectToRemove);
                    break;
                }
            }  
        }

这工作正常。只是我想防止Rectangle彼此重叠,并且必须通过自动调整一个接一个地出现。

帮助赞赏!

4

4 回答 4

1

为了获得您想要的效果,您必须将 Canvas 更改为 WrapPanel。这样,当您将子项添加到画布时,您不会添加位置,它会自行排列对象。基本上你想要这个

      <ScrollViewer VerticalScrollBarVisibility="Auto" >
        <WrapPanel Name="objList" > </WrapPanel>
      </ScrollViewer>

如果您的对象多于窗口可以包含的数量,则 ScrollViewer 将允许您滚动。

于 2013-07-11T12:55:55.007 回答
1

是否需要具体Canvas..?即使在纯 WPF/Desktop 中,也有一些布局组件可以完全自动地为您执行此操作。

一个接一个地“堆叠”组件的行为正是StackPanel类/组件/控件所做的:

<StackPanel x:Name="stacker" Orientation="Vertical">
    <Rectangle Width="30" Height="100" Background="Green" />
    <Rectangle Width="10" Height="50" Background="Blue" />
    <Rectangle Width="20" Height="80" Background="Red" Margin="5,10" />
</StackPanel>

请注意矩形是如何根据它们的不同被定位在另一个之下的Heights。请注意,我不必指定Orientation=Vertical,因为 StackPanel 的默认行为是这样定位它们。您可以根据需要将其切换为水平,然后它将根据它们的Widths. 您还可以使用 ie 微调并添加一些额外的间距,Margin就像在第三个矩形中一样。

如果您需要通过代码来完成,那么StackPanelnamedstacker非常适合它:您可以动态地向它添加新元素,它会像在 XAML 中定义的子元素一样布置添加的元素:一个在另一个之下。

使用 StackPanel,您可以获得更多!StackPanel 观察它的孩子。如果在放置孩子之后的某个时间你改变孩子的高度/宽度,那么 StackPanel 将立即调整位置,使它们不重叠(如果你让孩子变小,它会挤压它们,如果你让孩子变大 - 它将扩大等)。

如果你真的很想使用Canvas,那么在添加新项目的那一刻,你将不得不遍历存储在画布中的所有现有项目,总结它们的高度,并设置新的 Y 位置项目正好那个总和。这样,它将恰好出现在最后一个元素的下方。这是最明显的做法。但是,它不会考虑边距、间距和其他一些可能恰好出现在画布上的细节。

一个更好但不太明显的方法是不要一次又一次地总结高度,而是根据最底部的现有项目定位新项目。毕竟,所有旧物品都放置正确,对吧?但是,是什么bottommost意思?有时,位于顶部附近的高大物品可能比位于中心的不那么高的物品向下延伸得更远。因此,bottommost并不意味着the item with maximum Y position而是意味着具有最远的项目Bottom,所以maximum Y+Height. 所以:

  • 遍历现有项目
  • 找到一个Size.Height+Position.Bottom最大的项目
  • Position.Y新项目的 设置为该值

现在,您将获得与 StackPanel 大致相同的效果 - 但它只是一次性效果。如果您稍后修改某些元素的高度,您将不得不重新计算所有位置并调整所有位置.. (*)

编辑:(*)我不记得了,但如果 X/Y/Bottom 属性是 DependencyProperty,那么您甚至可以尝试使用绑定来自动控制位置。Tha 在 Canvas 上可能会很有趣。Y只需尝试将后一个元素的 a绑定到前一个元素Bottom,它就会神奇地自行布局它们,甚至在移动/调整大小时自动更新。不过,请先尝试 StackPanel!

于 2013-07-11T12:57:20.483 回答
0

听起来你想要一个StackPanel矩形。您可以将 StackPanel 嵌套在 Grid 中。

于 2013-07-11T12:54:11.647 回答
0

这是我的解决方案:

<ScrollViewer VerticalScrollBarVisibility="Auto" Width="250" Height="500">
                <WrapPanel Name="wrapboard" Orientation="Vertical" ></WrapPanel>
     </ScrollViewer>

private void BtnAdd_Click(object sender, RoutedEventArgs e)
        {

            int heigt = 0;
            int wegt = 0;
             if (!string.IsNullOrEmpty(txtHeight.Text) && !string.IsNullOrEmpty(txtWidth.Text))
            {
                heigt = int.Parse(txtHeight.Text);
                wegt = int.Parse(txtWidth.Text);
            }
            rect = new Rectangle();
            rect.Stroke = Brushes.Red;
            rect.StrokeThickness = 2;
            rect.Height = heigt;
            rect.Width = wegt;
            rect.Tag = val;
            wrapboard.Children.Add(rect);
            val = val + 1;
            //wrapboard is WrapPanel object
            foreach (UIElement ui in wrapboard.Children)
            {
                if (ui.GetType() == typeof(Rectangle))
                {
                    itemstoremove.Add(ui);
                }
            }
        }
于 2013-07-11T13:32:16.420 回答