如何使用C#在WPF中的Resized父Rectangle旁边移动Rectangle?

时间:2013-07-11 12:33:18

标签: c# wpf canvas rectangles

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

例如:。 当有3个带有{​​{1}},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; } } } 相互重叠,并且必须使用自动调整逐个显示。

帮助感谢!

4 个答案:

答案 0 :(得分:1)

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

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

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

答案 1 :(得分:1)

是否需要具体Canvas ..?即使在纯WPF /桌面中,也有一些布局组件可以为您完成此操作,强制自动。

&#34;堆叠&#34;的行为一个接一个的组件正是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将它们堆叠起来。您还可以使用Margin进行微调并添加一些额外的间距,如第三个矩形所示。

如果您需要通过代码执行此操作,那么名为StackPanel的{​​{1}}非常适合它:您可以动态添加新元素,它会像添加它一样添加新元素在XAML中定义的子项:一个在另一个下面。

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

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

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

  • 循环现有项目
  • 找到maximum Y+Height最大的项目
  • 将新项目的Size.Height+Position.Bottom设置为该值

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

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

答案 2 :(得分:0)

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

答案 3 :(得分: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);
                }
            }
        }