【wpf】05 几种容器动态创建控件的对比

news2024/10/23 17:25:57

在这里插入图片描述
今天利用一点时间,对wpf中在常用容器中动态创建控件的方法进行了学习和测试,本篇文章用来记录这个过程及一些心得。

1 容器说明

用于对比的wpf常用容器类包括如下七种:

  • StackPanel
  • Grid
  • ScrollViewer
  • WrapPanel
  • Canvas
  • UniformGrid
  • DockPanel
    以上每个类中的属性和方法都有很多,就不一一尝试,只做最基础的动态控件创建显示。

1.1 StackPanel

布局特点:

StackPanel按照垂直(默认)或水平方向堆叠其子元素。
子元素不会自动换行,而是依次排列。

动态添加控件:

可以通过Children.Add方法动态添加控件。
新添加的控件会自动按照StackPanel的排列方向放置在现有控件的后面。

适用场景:

适用于需要简单堆叠控件的场景,如垂直或水平菜单、表单字段等。

1.2 Grid

布局特点:

Grid将布局划分为行和列的网格。
子元素可以放置在特定的单元格中,支持跨行跨列。
提供了更灵活和复杂的布局能力。

动态添加控件:

需要先定义行和列,然后通过Children.Add方法添加控件。
新添加的控件需要指定其所在的行和列,可以使用Grid.RowGrid.Column附加属性。
可以通过RowDefinitionsColumnDefinitions动态添加行和列。

适用场景:

适用于需要复杂布局的场景,如表单、数据网格、自定义用户界面等。

1.3 ScrollViewer

布局特点:

ScrollViewer用于提供滚动功能,使其内容在视图窗口中可见。
它只能包含一个直接子元素,但这个子元素可以是另一个布局容器(如StackPanelGrid等),从而间接包含多个控件。

动态添加控件:

由于ScrollViewer只能有一个直接子元素,因此通常会在其内部放置一个布局容器(如StackPanelGrid)。
然后在这个布局容器中动态添加控件。
当内容超出ScrollViewer的视图范围时,会自动出现滚动条。

适用场景:

适用于需要滚动功能的场景,如长列表、详细报告、大型表单等。

1.4 WrapPanel

布局特点:

WrapPanel按照水平或垂直方向排列其子元素。
当一行或一列的空间不足时,子元素会自动换行到下一行或下一列。

动态添加控件:

可以通过Children.Add方法动态添加控件。
新添加的控件会自动按照WrapPanel的排列方向放置在现有控件的后面,并在必要时换行。

适用场景:

适用于需要自动换行的布局场景,如水平或垂直排列的图标、文本等。

1.5 Canvas

布局特点:

Canvas允许通过绝对坐标来定位其子元素。
子元素可以放置在Canvas的任何位置,不受其他子元素的影响。

动态添加控件:

可以通过Children.Add方法动态添加控件。
新添加的控件需要使用Canvas.LeftCanvas.Top附加属性来指定其位置。

适用场景:

适用于需要精确控制子元素位置的场景,如绘图应用、自定义布局等。

1.6 UniformGrid

布局特点:

UniformGrid将布局划分为多个大小相同的单元格,并自动将子元素分配到这些单元格中。
子元素在UniformGrid中按照行和列的顺序排列。

动态添加控件:

可以通过Children.Add方法动态添加控件。
新添加的控件会自动分配到下一个可用的单元格中。

适用场景:

适用于需要创建均匀网格布局的场景,如图标网格、按钮网格等。

1.7 DockPanel

布局特点:

DockPanel允许其子元素停靠在容器的边缘(顶部、底部、左侧、右侧)或填充剩余的空间。
子元素的停靠顺序和填充方式可以通过Dock属性来指定。

动态添加控件:

可以通过Children.Add方法动态添加控件。
新添加的控件需要设置其Dock属性来指定停靠位置。

适用场景:

适用于需要创建停靠布局的场景,如工具栏、侧边栏等。

2 编码对比效果

在同一个Window中创建多个容器,为保证不同容器可以正常显示,这里我们采用使用框架元素(Framework Element)的Visibility属性,通过动态地改变容器的Visibility属性(设置为Visible或Collapsed),你可以控制哪些容器是可见的。设置为Collapsed的容器将不会占用布局空间,也不会渲染其内容,这有助于确保只有最上层的容器是可见的。

参考内容如下:

在用户界面设计中,当你需要在不同的容器(如视图、面板或窗口)之间切换,并且希望只有最上层的容器显示其内容,而其他容器则保持背景透明时,你可以采取以下几种方法来实现这一效果:

  1. 使用堆叠布局(Stack Layout):
    如果你使用的是像XAML(在WPF、UWP或Xamarin中)这样的标记语言,你可以使用堆叠布局(如StackPanel在WPF中)来重叠放置容器。通过设置容器的Background属性为透明(或在XAML中使用Transparent关键字),你可以确保它们不会遮挡彼此的内容,除非它们包含非透明的元素。最上层的容器将显示其内容,因为它会覆盖在下层容器的上方。
  2. 使用框架元素(Framework Element)的Visibility属性:
    通过动态地改变容器的Visibility属性(设置为Visible或Collapsed),你可以控制哪些容器是可见的。设置为Collapsed的容器将不会占用布局空间,也不会渲染其内容,这有助于确保只有最上层的容器是可见的。
  3. 使用Z-Index或类似的层级控制:
    在某些UI框架中,你可以通过调整元素的Z-Index来控制它们的堆叠顺序。虽然XAML本身没有直接的Z-Index属性,但你可以通过调整容器在布局中的顺序或使用Canvas布局并设置Canvas.ZIndex属性来实现类似的效果。
  4. 使用弹出窗口(Popup)或模态对话框:
    如果你希望某个容器能够完全覆盖其他容器,并且不希望其他容器的内容干扰到用户交互,你可以使用弹出窗口(如WPF中的Popup控件)或模态对话框。这些元素通常会在其他内容之上显示,并且可以配置为具有透明背景。
  5. 自定义渲染和布局逻辑:
    如果你使用的UI框架没有提供直接支持这种效果的方法,你可能需要自定义渲染和布局逻辑。这通常涉及到对UI元素的深入理解和对框架底层工作原理的掌握。
    使用动画和过渡效果:
    为了提供更平滑的用户体验,你可以在容器之间切换时使用动画和过渡效果。这不仅可以增强视觉效果,还可以帮助用户更好地理解哪些内容是当前活动的。
    请注意,具体实现方法将取决于你使用的UI框架和编程语言。在WPF中,你可以使用上述方法中的任何一种或组合使用它们来实现容器之间的切换效果。在其他UI框架中,虽然具体的属性和方法可能有所不同,但基本原理是相似的。

Xmal代码:

<Window x:Class="ContainerTestWpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:ContainerTestWpfApp"
        mc:Ignorable="d"
        Title="MainWindow" Height="768" Width="1024"
        WindowStartupLocation="CenterScreen">
    <Grid x:Name="MainGrid">
        <Button x:Name="BtnStackPanel" Content="StackPanel" HorizontalAlignment="Left" Margin="20,30,0,0" VerticalAlignment="Top" Width="80" Click="BtnStackPanel_Click"/>
        <Button x:Name="BtnGrid" Content="Grid" HorizontalAlignment="Left" Margin="120,30,0,0" VerticalAlignment="Top" Width="80" Click="BtnGrid_Click"/>
        <Button x:Name="BtnScrollViewer" Content="ScrollViewer" HorizontalAlignment="Left" Margin="220,30,0,0" VerticalAlignment="Top" Width="80" Click="BtnScrollViewer_Click"/>
        <Button x:Name="BtnWrapPanel" Content="WrapPanel" HorizontalAlignment="Left" Margin="320,30,0,0" VerticalAlignment="Top" Width="80" Click="BtnWrapPanel_Click"/>
        <Button x:Name="BtnCanvas" Content="Canvas" HorizontalAlignment="Left" Margin="420,30,0,0" VerticalAlignment="Top" Width="80" Click="BtnCanvas_Click"/>
        <Button x:Name="BtnUniformGrid" Content="UniformGrid" HorizontalAlignment="Left" Margin="520,30,0,0" VerticalAlignment="Top" Width="80" Click="BtnUniformGrid_Click"/>
        <Button x:Name="BtnDockPanel" Content="DockPanel" HorizontalAlignment="Left" Margin="620,30,0,0" VerticalAlignment="Top" Width="80" Click="BtnDockPanel_Click"/>
        <!-- 容器StackPanel -->
        <StackPanel x:Name="ContainerStackPanel" HorizontalAlignment="Left" Margin="20,70,0,0" VerticalAlignment="Top" Width="800" Height="600" >

        </StackPanel>
        <!-- 容器Grid -->
        <Grid x:Name="ContainerGrid" Grid.Column="0" HorizontalAlignment="Left" Margin="20,70,0,0" VerticalAlignment="Top" Width="800" Height="600">

        </Grid>
        <!-- 容器ScrollViewer -->
        <ScrollViewer x:Name="ContainerScrollViewer" HorizontalAlignment="Left" Margin="20,70,0,0" VerticalAlignment="Top" Width="800" Height="600">
            <Grid x:Name="SVGrid">
                
            </Grid>
        </ScrollViewer>
        <!-- 容器WrapPanel -->
        <WrapPanel x:Name="ContainerWrapPanel" HorizontalAlignment="Left" Margin="20,70,0,0" VerticalAlignment="Top" Width="800" Height="600">

        </WrapPanel>
        <!-- 容器Canvas -->
        <Canvas x:Name="ContainerCanvas" HorizontalAlignment="Left" Margin="20,70,0,0" VerticalAlignment="Top" Width="800" Height="600">

        </Canvas>
        <!-- 容器UniformGrid -->
        <UniformGrid x:Name="ContainerUniformGrid" HorizontalAlignment="Left" Margin="20,70,0,0" VerticalAlignment="Top" Width="800" Height="600">

        </UniformGrid>
        <!-- 容器DockPanel -->
        <DockPanel x:Name="ContainerDockPanel" HorizontalAlignment="Left" Margin="20,70,0,0" VerticalAlignment="Top" Width="800" Height="600">

        </DockPanel>
        <Image HorizontalAlignment="Left" Height="100" Margin="880,90,0,0" VerticalAlignment="Top" Width="100" Source="/test.png"/>

    </Grid>
</Window>

用于显示容器效果的CSharp代码:

// 用于切换容器显示
this.ContainerStackPanel.Visibility = Visibility.Visible;
this.ContainerGrid.Visibility = Visibility.Collapsed;
this.ContainerScrollViewer.Visibility = Visibility.Collapsed;
this.ContainerCanvas.Visibility = Visibility.Collapsed;
this.ContainerUniformGrid.Visibility = Visibility.Collapsed;
this.ContainerWrapPanel.Visibility = Visibility.Collapsed;
this.ContainerDockPanel.Visibility = Visibility.Collapsed;

2.1 StackPanel

控制代码:

       /// <summary>
       /// 在容器StackPanel中动态创建控件
       /// </summary>
       /// <param name="sender"></param>
       /// <param name="e"></param>
       private void BtnStackPanel_Click(object sender, RoutedEventArgs e)
       {
           ClearAllItems();
           // 用于切换容器显示
           this.ContainerStackPanel.Visibility = Visibility.Visible;
           this.ContainerGrid.Visibility = Visibility.Collapsed;
           this.ContainerScrollViewer.Visibility = Visibility.Collapsed;
           this.ContainerCanvas.Visibility = Visibility.Collapsed;
           this.ContainerUniformGrid.Visibility = Visibility.Collapsed;
           this.ContainerWrapPanel.Visibility = Visibility.Collapsed;
           this.ContainerDockPanel.Visibility = Visibility.Collapsed;

           this.BtnStackPanel.Background = new SolidColorBrush(Colors.Gray);
           this.BtnScrollViewer.Background = new SolidColorBrush(Colors.Blue);
           this.BtnCanvas.Background = new SolidColorBrush(Colors.Blue);
           this.BtnUniformGrid.Background = new SolidColorBrush(Colors.Blue);
           this.BtnWrapPanel.Background = new SolidColorBrush(Colors.Blue);
           this.BtnDockPanel.Background = new SolidColorBrush(Colors.Blue);

           int numberOfButtons = 10;

           for (int i = 0; i < numberOfButtons; i++)
           {
               // 添加按钮  
               Button button = new()
               {
                   Content = "Button " + i.ToString(), // 设置按钮内容
                   Tag = i,
               };
               button.Click += Button_Click; // 添加点击事件处理程序 
               ContainerStackPanel.Children.Add(button);

               // 添加文本块  
               TextBlock textBlock = new()
               {
                   Text = "TextBlock " + i,// 设置按钮内容
                   Margin = new Thickness(0, 10, 0, 0) // 添加一些外边距
               };
               ContainerStackPanel.Children.Add(textBlock);

               // 获取当前执行程序集的名称  
               string? assemblyName = Assembly.GetExecutingAssembly().GetName().Name;

               // 构建 URI 来访问嵌入的资源  
               Uri uri = new($"pack://application:,,,/{assemblyName};component/test.png");

               // 添加图片
               Image image = new()
               {
                   Source = new BitmapImage(uri),
                   Height = 128, // 设置图片高度 
                   Width = 128,  // 设置图片宽度  
                   Margin = new Thickness(0, 10, 0, 0) // 添加一些外边距 
               };
               ContainerStackPanel.Children.Add(image);

               // 添加列表框  
               ListBox listBox = new();
               listBox.Items.Add("Item 1");
               listBox.Items.Add("Item 2");
               listBox.Items.Add("Item 3");
               listBox.Margin = new Thickness(0, 10, 0, 0); // 添加一些外边距  
               ContainerStackPanel.Children.Add(listBox);
           }
       }

执行效果:
在这里插入图片描述

2.2 Grid

这里需要说明一下,因为在创建项目的时候,已经存在一个主Grid了,这个Grid容器需要设置在主Grid内部,为了保证其正常显示,需要在Xmal的代码中对它在主Grid中的网格归属进行定义,不然就不会正常显示了。如上面代码中的这个 Grid.Column="0"属性。
控制代码:

        /// <summary>
        /// 在容器Grid中动态创建控件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnGrid_Click(object sender, RoutedEventArgs e)
        {
            ClearAllItems();
            // 用于切换容器显示
            this.ContainerStackPanel.Visibility = Visibility.Collapsed;
            this.ContainerGrid.Visibility = Visibility.Visible;
            this.ContainerScrollViewer.Visibility = Visibility.Collapsed;
            this.ContainerCanvas.Visibility = Visibility.Collapsed;
            this.ContainerUniformGrid.Visibility = Visibility.Collapsed;
            this.ContainerWrapPanel.Visibility = Visibility.Collapsed;
            this.ContainerDockPanel.Visibility = Visibility.Collapsed;

            this.BtnStackPanel.Background = new SolidColorBrush(Colors.Blue);
            this.BtnGrid.Background = new SolidColorBrush(Colors.Gray);
            this.BtnScrollViewer.Background = new SolidColorBrush(Colors.Blue);
            this.BtnCanvas.Background = new SolidColorBrush(Colors.Blue);
            this.BtnUniformGrid.Background = new SolidColorBrush(Colors.Blue);
            this.BtnWrapPanel.Background = new SolidColorBrush(Colors.Blue);
            this.BtnDockPanel.Background = new SolidColorBrush(Colors.Blue);

            int numberOfButtons = 10;

            for (int i = 0; i < numberOfButtons; i++)
            {
                RowDefinition rowDef = new RowDefinition
                {
                    Height = new GridLength(130, GridUnitType.Pixel)
                };
                ContainerGrid.RowDefinitions.Add(rowDef);

                // 添加按钮  
                Button button = new()
                {
                    Content = "Button " + i.ToString(), // 设置按钮内容
                    Tag = i,
                    HorizontalAlignment = HorizontalAlignment.Left,
                    VerticalAlignment = VerticalAlignment.Center,
                    Margin=new Thickness(10, 0, 0, 0)
                };
                button.Click += Button_Click; // 添加点击事件处理程序 
                Grid.SetRow(button, i); 
                ContainerGrid.Children.Add(button);

                // 添加文本块  
                TextBlock textBlock = new()
                {
                    HorizontalAlignment = HorizontalAlignment.Left,
                    VerticalAlignment = VerticalAlignment.Center,
                    Text = "TextBlock " + i,// 设置按钮内容
                    Margin = new Thickness(200, 0, 0, 0) // 添加一些外边距
                };
                Grid.SetRow(textBlock, i); 
                ContainerGrid.Children.Add(textBlock);

                // 获取当前执行程序集的名称  
                string? assemblyName = Assembly.GetExecutingAssembly().GetName().Name;

                // 构建 URI 来访问嵌入的资源  
                Uri uri = new($"pack://application:,,,/{assemblyName};component/test.png");

                // 添加图片
                Image image = new()
                {
                    Source = new BitmapImage(uri),
                    Height = 128, // 设置图片高度 
                    Width = 128,  // 设置图片宽度  
                    HorizontalAlignment = HorizontalAlignment.Left,
                    VerticalAlignment = VerticalAlignment.Center,
                    Margin = new Thickness(500, 0, 0, 0) // 添加一些外边距 
                };
                Grid.SetRow(image, i); 
                ContainerGrid.Children.Add(image);
            }
        }

执行效果:
在这里插入图片描述

2.3 ScrollViewer

控制代码:

        /// <summary>
        /// 在容器ScrollViewer中动态创建控件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnScrollViewer_Click(object sender, RoutedEventArgs e)
        {
            ClearAllItems();
            // 用于切换容器显示
            this.ContainerStackPanel.Visibility = Visibility.Collapsed;
            this.ContainerGrid.Visibility = Visibility.Collapsed;
            this.ContainerScrollViewer.Visibility = Visibility.Visible;
            this.ContainerCanvas.Visibility = Visibility.Collapsed;
            this.ContainerUniformGrid.Visibility = Visibility.Collapsed;
            this.ContainerWrapPanel.Visibility = Visibility.Collapsed;
            this.ContainerDockPanel.Visibility = Visibility.Collapsed;

            this.BtnStackPanel.Background = new SolidColorBrush(Colors.Blue);
            this.BtnGrid.Background = new SolidColorBrush(Colors.Blue);
            this.BtnScrollViewer.Background = new SolidColorBrush(Colors.Gray);
            this.BtnCanvas.Background = new SolidColorBrush(Colors.Blue);
            this.BtnUniformGrid.Background = new SolidColorBrush(Colors.Blue);
            this.BtnWrapPanel.Background = new SolidColorBrush(Colors.Blue);
            this.BtnDockPanel.Background = new SolidColorBrush(Colors.Blue);

            int numberOfButtons = 10;

            for (int i = 0; i < numberOfButtons; i++)
            {
                RowDefinition rowDef = new RowDefinition
                {
                    Height = new GridLength(150, GridUnitType.Pixel)
                };
                SVGrid.RowDefinitions.Add(rowDef);

                SVGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(800, GridUnitType.Pixel) });

                // 添加按钮  
                Button button = new()
                {
                    Content = "Button " + i.ToString(), // 设置按钮内容
                    Tag = i,
                    HorizontalAlignment = HorizontalAlignment.Left,
                    VerticalAlignment = VerticalAlignment.Center,
                    Margin = new Thickness(50, 0, 0, 0)
                };
                button.Click += Button_Click; // 添加点击事件处理程序 
                Grid.SetRow(button, i);
                Grid.SetColumn(button, 0);
                SVGrid.Children.Add(button);

                // 添加文本块  
                TextBlock textBlock = new()
                {
                    HorizontalAlignment = HorizontalAlignment.Left,
                    VerticalAlignment = VerticalAlignment.Center,
                    Text = "TextBlock " + i,// 设置按钮内容
                    Margin = new Thickness(200, 0, 0, 0) // 添加一些外边距
                };
                Grid.SetRow(textBlock, i);
                Grid.SetColumn(textBlock, 0);
                SVGrid.Children.Add(textBlock);

                // 获取当前执行程序集的名称  
                string? assemblyName = Assembly.GetExecutingAssembly().GetName().Name;

                // 构建 URI 来访问嵌入的资源  
                Uri uri = new($"pack://application:,,,/{assemblyName};component/test.png");

                // 添加图片
                Image image = new()
                {
                    Source = new BitmapImage(uri),
                    Height = 128, // 设置图片高度 
                    Width = 128,  // 设置图片宽度  
                    HorizontalAlignment = HorizontalAlignment.Left,
                    VerticalAlignment = VerticalAlignment.Center,
                    Margin = new Thickness(500, 0, 0, 0) // 添加一些外边距 
                };
                Grid.SetRow(image, i);
                Grid.SetColumn(image, 0);
                SVGrid.Children.Add(image);

                // 生成Rectangle控件
                Rectangle rectangle = new()
                {
                    Width = 750,
                    Height = 140,
                    Stroke = Brushes.Gray,
                    HorizontalAlignment = HorizontalAlignment.Left,
                    VerticalAlignment = VerticalAlignment.Center,
                    Margin = new Thickness(20, 0, 0, 0)
                };
                Grid.SetRow(rectangle, i);
                Grid.SetColumn(rectangle, 0);
                SVGrid.Children.Add(rectangle);
            }
        }

执行效果:
在这里插入图片描述

2.4 WrapPanel

控制代码:

        /// <summary>
        /// 在容器WrapPanel中动态创建控件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnWrapPanel_Click(object sender, RoutedEventArgs e)
        {
            ClearAllItems();
            // 用于切换容器显示
            this.ContainerStackPanel.Visibility = Visibility.Collapsed;
            this.ContainerGrid.Visibility = Visibility.Collapsed;
            this.ContainerScrollViewer.Visibility = Visibility.Collapsed;
            this.ContainerCanvas.Visibility = Visibility.Collapsed;
            this.ContainerUniformGrid.Visibility = Visibility.Collapsed;
            this.ContainerWrapPanel.Visibility = Visibility.Visible;
            this.ContainerDockPanel.Visibility = Visibility.Collapsed;

            this.BtnStackPanel.Background = new SolidColorBrush(Colors.Blue);
            this.BtnGrid.Background = new SolidColorBrush(Colors.Blue);
            this.BtnScrollViewer.Background = new SolidColorBrush(Colors.Blue);
            this.BtnCanvas.Background = new SolidColorBrush(Colors.Blue);
            this.BtnUniformGrid.Background = new SolidColorBrush(Colors.Blue);
            this.BtnWrapPanel.Background = new SolidColorBrush(Colors.Gray);
            this.BtnDockPanel.Background = new SolidColorBrush(Colors.Blue);

            int numberOfButtons = 10;

            for (int i = 0; i < numberOfButtons; i++)
            {
                // 添加按钮  
                Button button = new()
                {
                    Content = "Button " + i.ToString(), // 设置按钮内容
                    Tag = i,
                    Width = 80,
                    Height = 50,
                    VerticalAlignment = VerticalAlignment.Center,
                    Margin = new Thickness(0,0,0,0)
                };
                button.Click += Button_Click; // 添加点击事件处理程序 
                ContainerWrapPanel.Children.Add(button);

                // 添加文本块  
                TextBlock textBlock = new()
                {
                    Text = "TextBlock " + i,// 设置按钮内容
                    VerticalAlignment = VerticalAlignment.Center,
                    Margin = new Thickness(0, 0, 0, 0) // 添加一些外边距
                };
                ContainerWrapPanel.Children.Add(textBlock);

                // 获取当前执行程序集的名称  
                string? assemblyName = Assembly.GetExecutingAssembly().GetName().Name;

                // 构建 URI 来访问嵌入的资源  
                Uri uri = new($"pack://application:,,,/{assemblyName};component/test.png");

                // 添加图片
                Image image = new()
                {
                    Source = new BitmapImage(uri),
                    Height = 128, // 设置图片高度 
                    Width = 128,  // 设置图片宽度  
                    Margin = new Thickness(0, 0, 0, 0) // 添加一些外边距 
                };
                ContainerWrapPanel.Children.Add(image);

                // 添加列表框  
                ListBox listBox = new();
                listBox.Items.Add("Item 1");
                listBox.Items.Add("Item 2");
                listBox.Items.Add("Item 3");
                listBox.Margin = new Thickness(0, 0, 0, 0); // 添加一些外边距  
                ContainerWrapPanel.Children.Add(listBox);
            }
        }

执行效果:
在这里插入图片描述

2.5 Canvas

控制代码:

        /// <summary>
        /// 在容器Canvas中动态创建控件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnCanvas_Click(object sender, RoutedEventArgs e)
        {
            ClearAllItems();
            // 用于切换容器显示
            this.ContainerStackPanel.Visibility = Visibility.Collapsed;
            this.ContainerGrid.Visibility = Visibility.Collapsed;
            this.ContainerScrollViewer.Visibility = Visibility.Collapsed;
            this.ContainerCanvas.Visibility = Visibility.Visible;
            this.ContainerUniformGrid.Visibility = Visibility.Collapsed;
            this.ContainerWrapPanel.Visibility = Visibility.Collapsed;
            this.ContainerDockPanel.Visibility = Visibility.Collapsed;

            this.BtnStackPanel.Background = new SolidColorBrush(Colors.Blue);
            this.BtnGrid.Background = new SolidColorBrush(Colors.Blue);
            this.BtnScrollViewer.Background = new SolidColorBrush(Colors.Blue);
            this.BtnCanvas.Background = new SolidColorBrush(Colors.Gray);
            this.BtnUniformGrid.Background = new SolidColorBrush(Colors.Blue);
            this.BtnWrapPanel.Background = new SolidColorBrush(Colors.Blue);
            this.BtnDockPanel.Background = new SolidColorBrush(Colors.Blue);

            int numberOfButtons = 10;

            for (int i = 0; i < numberOfButtons; i++)
            {
                // 添加按钮  
                Button button = new()
                {
                    Content = "Button " + i.ToString(), // 设置按钮内容
                    Tag = i,
                    Width = 80,
                    Height = 50,
                    VerticalAlignment = VerticalAlignment.Center
                };
                button.Click += Button_Click; // 添加点击事件处理程序 
                // 设置按钮在 Canvas 上的位置  
                Canvas.SetLeft(button, 10); // 每个按钮间隔 10 像素加上按钮宽度 100 像素  
                Canvas.SetTop(button, i*130);       // 所有按钮都在 Canvas 的顶部开始,距离顶部 10 像素  

                ContainerCanvas.Children.Add(button);

                // 添加文本块  
                TextBlock textBlock = new()
                {
                    Text = "TextBlock " + i,// 设置按钮内容
                    VerticalAlignment = VerticalAlignment.Center
                };
                Canvas.SetLeft(textBlock, 300);  
                Canvas.SetTop(textBlock, i * 130);
                ContainerCanvas.Children.Add(textBlock);

                // 获取当前执行程序集的名称  
                string? assemblyName = Assembly.GetExecutingAssembly().GetName().Name;

                // 构建 URI 来访问嵌入的资源  
                Uri uri = new($"pack://application:,,,/{assemblyName};component/test.png");

                // 添加图片
                Image image = new()
                {
                    Source = new BitmapImage(uri),
                    Height = 128, // 设置图片高度 
                    Width = 128,  // 设置图片宽度  
                };
                Canvas.SetLeft(image, 500);
                Canvas.SetTop(image, i * 130);
                ContainerCanvas.Children.Add(image);

                // 添加列表框  
                ListBox listBox = new();
                listBox.Items.Add("Item 1");
                listBox.Items.Add("Item 2");
                listBox.Items.Add("Item 3");
                Canvas.SetLeft(listBox, 700);
                Canvas.SetTop(listBox, i * 130);
                ContainerCanvas.Children.Add(listBox);
            }
        }

执行效果:
在这里插入图片描述

2.6 UniformGrid

控制代码:

        /// <summary>
        /// 在容器UniformGrid中动态创建控件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnUniformGrid_Click(object sender, RoutedEventArgs e)
        {
            ClearAllItems();
            // 用于切换容器显示
            this.ContainerStackPanel.Visibility = Visibility.Collapsed;
            this.ContainerGrid.Visibility = Visibility.Collapsed;
            this.ContainerScrollViewer.Visibility = Visibility.Collapsed;
            this.ContainerCanvas.Visibility = Visibility.Collapsed;
            this.ContainerUniformGrid.Visibility = Visibility.Visible;
            this.ContainerWrapPanel.Visibility = Visibility.Collapsed;
            this.ContainerDockPanel.Visibility = Visibility.Collapsed;

            this.BtnStackPanel.Background = new SolidColorBrush(Colors.Blue);
            this.BtnGrid.Background = new SolidColorBrush(Colors.Blue);
            this.BtnScrollViewer.Background = new SolidColorBrush(Colors.Blue);
            this.BtnCanvas.Background = new SolidColorBrush(Colors.Blue);
            this.BtnUniformGrid.Background = new SolidColorBrush(Colors.Gray);
            this.BtnWrapPanel.Background = new SolidColorBrush(Colors.Blue);
            this.BtnDockPanel.Background = new SolidColorBrush(Colors.Blue);

            int numberOfButtons = 10;

            for (int i = 0; i < numberOfButtons; i++)
            {
                // 添加按钮  
                Button button = new()
                {
                    Content = "Button " + i.ToString(), // 设置按钮内容
                    Tag = i,
                    Width = 80,
                    Height = 50,
                };
                button.Click += Button_Click; // 添加点击事件处理程序 
                ContainerUniformGrid.Children.Add(button);

                // 添加文本块  
                TextBlock textBlock = new()
                {
                    Text = "TextBlock " + i,// 设置按钮内容
                };
                ContainerUniformGrid.Children.Add(textBlock);

                // 获取当前执行程序集的名称  
                string? assemblyName = Assembly.GetExecutingAssembly().GetName().Name;

                // 构建 URI 来访问嵌入的资源  
                Uri uri = new($"pack://application:,,,/{assemblyName};component/test.png");

                // 添加图片
                Image image = new()
                {
                    Source = new BitmapImage(uri),
                    Height = 64, // 设置图片高度 
                    Width = 64,  // 设置图片宽度  
                };

                ContainerUniformGrid.Children.Add(image);

                // 添加列表框  
                ListBox listBox = new();
                listBox.Items.Add("Item 1");
                listBox.Items.Add("Item 2");
                listBox.Items.Add("Item 3");
                ContainerUniformGrid.Children.Add(listBox);
            }
        }

执行效果:
在这里插入图片描述

2.7 DockPanel

这里测试了几种布局,但考虑到多种控件在这个容器中生成,会很混乱,就选择其中一种作为对比实验。
控制代码:

       /// <summary>
       /// 在容器DockPanel中动态创建控件
       /// </summary>
       /// <param name="sender"></param>
       /// <param name="e"></param>
       private void BtnDockPanel_Click(object sender, RoutedEventArgs e)
       {
           ClearAllItems();
           // 用于切换容器显示
           this.ContainerStackPanel.Visibility = Visibility.Collapsed;
           this.ContainerGrid.Visibility = Visibility.Collapsed;
           this.ContainerScrollViewer.Visibility = Visibility.Collapsed;
           this.ContainerCanvas.Visibility = Visibility.Collapsed;
           this.ContainerUniformGrid.Visibility = Visibility.Collapsed;
           this.ContainerWrapPanel.Visibility = Visibility.Collapsed;
           this.ContainerDockPanel.Visibility = Visibility.Visible;

           this.BtnStackPanel.Background = new SolidColorBrush(Colors.Blue);
           this.BtnGrid.Background = new SolidColorBrush(Colors.Blue);
           this.BtnScrollViewer.Background = new SolidColorBrush(Colors.Blue);
           this.BtnCanvas.Background = new SolidColorBrush(Colors.Blue);
           this.BtnUniformGrid.Background = new SolidColorBrush(Colors.Blue);
           this.BtnWrapPanel.Background = new SolidColorBrush(Colors.Blue);
           this.BtnDockPanel.Background = new SolidColorBrush(Colors.Gray);

           int numberOfButtons = 10;

           for (int i = 0; i < numberOfButtons; i++)
           {
               // 添加按钮  
               Button button = new()
               {
                   Content = "Button " + i.ToString(), // 设置按钮内容
                   Tag = i,
                   Width = 80,
                   Height = 50,
               };
               button.Click += Button_Click; // 添加点击事件处理程序 
               DockPanel.SetDock(button, Dock.Top);
               ContainerDockPanel.Children.Add(button);

               // 添加文本块  
               TextBlock textBlock = new()
               {
                   Text = "TextBlock " + i,// 设置按钮内容
               };
               DockPanel.SetDock(textBlock, Dock.Left);
               ContainerDockPanel.Children.Add(textBlock);

               // 获取当前执行程序集的名称  
               string? assemblyName = Assembly.GetExecutingAssembly().GetName().Name;

               // 构建 URI 来访问嵌入的资源  
               Uri uri = new($"pack://application:,,,/{assemblyName};component/test.png");

               // 添加图片
               Image image = new()
               {
                   Source = new BitmapImage(uri),
                   Height = 64, // 设置图片高度 
                   Width = 64,  // 设置图片宽度  
               };
               DockPanel.SetDock(textBlock, Dock.Top);
               ContainerDockPanel.Children.Add(image);

                添加列表框  
               //ListBox listBox = new();
               //listBox.Items.Add("Item 1");
               //listBox.Items.Add("Item 2");
               //listBox.Items.Add("Item 3");
               //DockPanel.SetDock(textBlock, Dock.Top);
               //ContainerDockPanel.Children.Add(listBox);
           }
       }

执行效果:
在这里插入图片描述

3 总结

从上面代码实现的效果来看,对于动态生成的控件可以分成两种可能性:
一是固定数量和种类的控件生成;
二是不固定数量和种类的控件生成。

从上面的实现效果可以明显看出,不固定数量的控件生成很容易超出容器范围,从而无法看到,那这里能够胜任此功能的只有使用ScrollViewer和其他容器的组合实现,效果是比较好的。

如下:
在这里插入图片描述
wpf中控件的灵活组合,还有很多值得深入学习的地方,在使用的过程中,逐渐进步。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2213187.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue实现动态表单

使用 Vue 实现动态表单 在前端开发中&#xff0c;我们经常遇到根据用户输入动态生成不同表单项的需求。这类动态表单不仅提升了用户体验&#xff0c;还可以让复杂的交互流程变得简洁而高效。本文将详细讲解如何使用 Vue 3 的响应式特性&#xff0c;逐步构建一个递归动态表单。…

服务器虚拟化的好处有哪些

1.什么是服务器虚拟化&#xff1f; 在计算服务中&#xff0c;有7种虚拟化包括硬件虚拟化&#xff08;即服务器虚拟化&#xff09;、软件虚拟化、内存虚拟化、存储虚拟化、数据虚拟化、网络虚拟化和桌面虚拟化。 其中&#xff0c;服务器虚拟化的初衷是让Windows和Linux操作系统…

【环境搭建】更换电脑后的开发环境怎么重建

目录 &#x1f378;前言 &#x1f37b;一、系统配置检查 &#x1f37a;二、开发环境搭建 &#x1f379;三、章末 &#x1f378;前言 小伙伴们大家好&#xff0c;这次文章跟技术没有关联&#xff0c;因为最近刚更换了装备&#xff0c;开发环境啥的残缺不全&#xff0c;也不能…

多倍体重测序-经典分析思路

你知道吗&#xff1f;甘蔗不仅是全球糖分的主要来源&#xff0c;而且它还隐藏着许多未被发掘的秘密。今天&#xff0c;我们就来聊聊科学家们是如何通过全基因组测序技术解开甘蔗品种改良之谜的&#xff01; 广东省科学院南繁种业研究所在《The Plant Journal》杂志上发表题为“…

vue3项目在vue平台下添加nvue文件会报[plugin:vite:nvue-css]

项目运行是会报大量的[plugin:vite:nvue-css]作警告 解决办法&#xff1a;在app.vue引入公共css文件外添加#ifndef APP-PLUS-NVUE条件 // #ifndef APP-PLUS-NVUE import "uview-plus/index.scss"; /*每个页面公共css */ import "colorui/main.css"; //#en…

微信小程序考试系统(lw+演示+源码+运行)

摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了微信小程序考试系统的开发全过程。通过分析微信小程序考试系统管理的不足&#xff0c;创建了一个计算机管理微信小程序考试系统的方案。文章介绍了微信小程序考…

Leetcode 1168. 水资源分配优化

1.题目基本信息 1.1.题目描述 村里面一共有 n 栋房子。我们希望通过建造水井和铺设管道来为所有房子供水。 对于每个房子 i&#xff0c;我们有两种可选的供水方案&#xff1a;一种是直接在房子内建造水井&#xff0c;成本为 wells[i – 1] &#xff08;注意 -1 &#xff0c;…

双十一买什么东西比较好?2024双11好物攻略诚意分享

双十一活动已经准备要开始了&#xff0c;很多人摩拳擦掌准备入手划算好物&#xff0c;但是有的人也比较迷茫&#xff0c;双十一买什么东西比较好&#xff1f;为了帮助大家在这场购物狂欢中理性消费&#xff0c;提升购物体验&#xff0c;我们精心整理了一份2024双11好物攻略诚意…

扭亏年只是开始,赛力斯的成长性仍在继续

赛力斯的三季度业绩报告发出之后&#xff0c;不少股民在评论区如释重负&#xff1a; 大雪压我两三年&#xff0c;我笑大雪轻如棉。 业绩预告显示&#xff0c;赛力斯2024年前三季度营业收入同比大增518%到559%&#xff0c;达1030.0亿元到1100.0亿元&#xff1b;同时净利润连续…

2018年计算机网络408真题解析

第一题&#xff1a; 解析&#xff1a;TCP/IP体系结构应用层常用协议及其相应的运输层协议 TCP协议是面向连接可靠数据传输服务&#xff0c;UDP无连接不可靠的数据传输服务&#xff0c;IP无连接不可靠的数据连接服务。 FTP协议&#xff0c;SMTP协议和HTTP协议使用TCP协议提供的面…

防爆手机能有多轻薄?AORO A29小身躯在石油化工有大作为!

防爆手机能有多轻薄&#xff1f;AORO A29防爆手机机身尺寸为177.4*81.5*12.75mm&#xff0c;重量仅为334.5g&#xff0c;其轻薄的设计在一众“砖头”工业防爆手机中脱颖而出。 轻薄是不是意味着功能削减&#xff1f;AORO A29防爆手机在保持轻薄体态的同时&#xff0c;集成了九…

数据结构(七大排序)

前言 前话&#xff1a;排序在我们日常中很常见&#xff0c;但在不同的场合我们需要选择不同的排序&#xff0c;因为每个排序都有不同的使用场景&#xff0c;不同的时间复杂度和空间复杂度&#xff1b;常见的排序分为七种&#xff0c; 插入排序、选择排序、交换排序和归并排序&…

2024 年 Mac 下这些生产力工具,好用到哭

每段关系最终都会结束 即使不是因为别的原因 也会因为死亡 我只知道 你不对她说出来 她就永远不知道 你的心意 她那天离开的时候 才知道一个道理 有时候 保护一样重要的东西的方式 不是守在她旁边 而是离开她 离得远远的远到看起来谁也 不在乎谁一样 今天呢&#x…

FPGA上板调试方式总结----VIO/ILA

在Vivado中&#xff0c;VIO&#xff08;Virtual Input/Output&#xff09;是一种用于调试和测试FPGA设计的IP核&#xff0c;它允许设计者通过JTAG接口实时读取和写入FPGA内部的寄存器&#xff0c;从而检查设计的运行状态并修改其行为。VIO IP核提供了一个简单易用的接口&#x…

Redis总结(官方文档解读)

定义 Redis是一个开源的&#xff0c;基于内存的数据结构存储系统&#xff0c;可以用作数据库、缓存和消息中间件。 特征 高性能 支持丰富的数据类型 丰富的操作类型&#xff0c;操作是原子性的 支持周期性持久化 支持分布式 开源免费&#xff0c;社区活跃 数据类型 数据…

图片加水印怎么弄?四款软件供你选择!

在这个信息爆炸的时代&#xff0c;每一张图片都可能成为你创意与努力的结晶。然而&#xff0c;网络上的复制粘贴如此轻易&#xff0c;如何有效保护自己的原创作品&#xff0c;防止未经授权的盗用&#xff0c;成为了每位创作者必须面对的问题。别担心&#xff0c;今天我们就来揭…

[Linux系统编程]线程概念,三级映射,线程操作函数

一.线程概念 线程概念&#xff1a; 进程&#xff1a;有独立的 进程地址空间。有独立的pcb。 进程是分配资源的最小单位。 线程&#xff1a;没有独立的进程地址空间。有独立的pcb。 进程是cup执行的最小单位。 线程有线程id和线程号&#xff0c;线程id是用于进程内部标识线程…

2024年10款超好用的图纸加密软件推荐|企业常用图纸加密软件分享

在数字化时代&#xff0c;图纸作为企业的关键技术资产&#xff0c;承载着大量敏感信息&#xff0c;泄露这些图纸不仅可能导致重大经济损失&#xff0c;还可能危及企业的市场竞争力。因此&#xff0c;选择一款合适的图纸加密软件&#xff0c;对企业而言至关重要。为了帮助企业保…

【C#网络编程】基础概念2

文章目录 网络、数据包和协议网络数据包协议TCP、UDP 地址客户端和服务器套接字 网络、数据包和协议 计算机网络通过通信通道互连的机器组成&#xff0c;通常把这些机器称为主机和路由器&#xff0c;主机是是运行应用程序&#xff08;如 Web 浏览器&#xff09;的计算机。路由器…

市面上琳琅满目的网站开发公司,如何避免“踩坑”?

服务品质和售后服务是选择网站开发公司时的两大关键因素—— 因为这些方面将直接影响网站的质量、用户体验以及后期的维护效果&#xff0c;一家优秀的网站开发公司&#xff0c;其服务品质应体现在专业的技术水平、出色的项目管理能力以及对客户需求的精准理解和高效执行上。 …