【问题标题】:How to Move Rectangle next to Resized parent Rectangle in WPF using C#?如何使用 C# 在 WPF 中将矩形移动到调整大小的父矩形旁边?
【发布时间】:2013-07-11 12:33:17
【问题描述】:

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

例如:。 当有 3 个矩形,Height=100,Width=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 相互重叠,并且必须使用自动调整一个接一个地出现。

帮助赞赏!

【问题讨论】:

    标签: c# wpf canvas rectangles


    【解决方案1】:

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

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

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

    【讨论】:

    • 你的意思是我必须将矩形添加到 WrapPanel 吗?我是新手,所以..!
    • 这是一个很好的建议,但是作者想把它们放在一个下面,至少我认为他在看到Canvas.SetLeft(rect, 10); Canvas.SetTop(rect, (rect.Height) * val);之后想要这样。
    • @SHEKHARSHETE:是的,他就是这个意思。 WrapPanel 将成为您的 Rectangles 的容器,然后 Rectangles 会像 HTML 页面上的文本一样对其进行布局:只要有空间,就紧紧地围绕,然后换行到“新行”。
    • 你好 quetzalcoatl & shmuelpro 我不知道我们是否会使用 WrapPanel。但是,现在我已经尝试使用 WrapPanel 了。谢谢! :)
    【解决方案2】:

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

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

    <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 堆叠它们。您还可以微调并添加一些额外的间距,即Margin,如第三个矩形中所示。

    如果您需要通过代码来完成,那么名为 stackerStackPanel 非常适合它:您可以动态地向其中添加新元素,它会像在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,那么您甚至可以尝试使用 Bindings 来自动控制位置。 Tha 在 Canvas 上可能会很有趣。只需尝试将后一个元素的Y 绑定到前一个元素的Bottom 上,它就会神奇地自行布局,甚至在移动/调整大小时自动更新。不过,请先尝试 StackPanel!

    【讨论】:

    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      这是我的解决方案:

      <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);
                      }
                  }
              }
      

      【讨论】:

        猜你喜欢
        • 2022-06-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-16
        • 1970-01-01
        相关资源
        最近更新 更多