如何使用C#在WPF中将矩形移动到已调整大小的父矩形旁边

本文关键字:调整 移动 何使用 WPF | 更新日期: 2023-09-27 18:21:54

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

例如: Height=100Width=200&当我设置CCD_ 3的高度时。则子CCD_ 4必须出现在第二矩形&不得重叠在第三个矩形上。有可能吗

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中将矩形移动到已调整大小的父矩形旁边

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

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

如果您的对象数量超过窗口所能容纳的数量,ScrollViewer将允许您滚动。

是否需要具体为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的默认行为是这样定位它们。如果你愿意,你可以将其切换到Horizontally,然后它会根据它们的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来自动控制位置。在画布上做这件事可能很有趣。只需尝试将后一个元素的Y绑定到前一个的Bottom,就可以神奇地自行布局,甚至在移动/调整大小时自动更新。不过,请先试试StackPanel!

听起来你想要一个StackPanel作为你的矩形。您可以将StackPanel嵌套在网格中。

这是我的解决方案:

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