WPF动态向容器添加自定义控件的问题

时间:2021-12-08 20:37:56
Winform中知道怎么做,但是WPF中不知道怎么加了。

需求是根据一些条件添加各种类型的用户控件,然后用户控件要从上往下的停靠着排序。

在Winform中我是先拖了一个panel
然后新建一个用户控件UserControl1  ucTemp = new UserControl1();
之后给控件赋值各种属性,然后让他自动停靠在控件上方...
ucTemp.Dock=DockStyle.Top
最后将控件赋值给Panel
Panel.Controls.Add(ucTemp);  


类似于这种功能,在WPF中应该如何编写?框架(上面的Panel)应该用什么替代? 另外还有个疑问,如果控件太多变卡了,操作延迟高有没有什么好的办法?比如框架中添加了上千控件,拖拽滚动条都会有延迟(winform里)。

17 个解决方案

#1


这个问题,一言难尽,先看个这个简单的例子看看对你有帮助没
绑定

#2


引用 1 楼 yysyangyangyangshan 的回复:
这个问题,一言难尽,先看个这个简单的例子看看对你有帮助没
绑定


有那么复杂吗?在winform里是一件很简单的事啊

就是动态向一个容器添加许多控件的代码要怎么写

#3


在自己的代码中截的一段。和winform里没多少区别啊。

      Image imageBottomIcon = new Image();
      try
      {
        imageBottomIcon.Source = new BitmapImage(new Uri(System.Windows.Forms.Application.StartupPath + "\\skins\\bottomIcon.png"));//90*146
      }
      catch { }
      gridBottom.Children.Add(imageBottomIcon);
      Grid.SetColumn(imageBottomIcon, Grid.GetColumn(imageBottomRight));

#4


WPF里面也有容器控件啊,差不多的呀!!!

#5


首先,在WPF中进行布局控制有几个主要的容器

Canvas是按照绝对位置定位的,很像上面的Panel这种机制;
StackPanel呢,则是基于流模式的,它没有绝对定位的概念,一批控件要么从左到右排列,要么从上而下排列
Grid,可能是用的最多的,它可以提供按照行和列的方式更好地组织控件。而事实上,在Grid里面也可以嵌入Canvas和StackPanel,他们结合可以构造出足够复杂的 界面。
第一部分是XAML代码

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="我的扫雷程序" Height="516" Width="592">
    <Grid>
        <Button Height="23" HorizontalAlignment="Left" Margin="20,12,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click">初级</Button>
        <Button Height="23" HorizontalAlignment="Left" Margin="101,12,0,0" Name="button2" VerticalAlignment="Top" Width="75" Click="button2_Click">高级</Button>
        <Canvas Margin="20,41,12,12" Name="canvas1"  />
    </Grid>
</Window>

using System.Windows;
using System.Windows.Controls;

namespace WpfApplication1
{
    /// <summary>
    /// Window1.xaml 的交互逻辑
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            CreateButton(6, 6);
        }


        private void button2_Click(object sender, RoutedEventArgs e)
        {
            CreateButton(9, 9);
        }

        private void CreateButton(int x, int y)
        {
            


            canvas1.Children.Clear();

            //四个方向的边距都是5
            double width = (this.canvas1.ActualWidth - (x + 1) * 5) / x;
            double height = (this.canvas1.ActualHeight - (y + 1) * 5) / y;




            for (int i = 0; i < x; i++)
            {
                for (int j = 0; j < y; j++)
                {
                    Button bt = new Button()
                    {
                        Width = width,
                        Height = height
                    };

                    Canvas.SetTop(bt, j * height + 5);
                    Canvas.SetLeft(bt, i * width + 5);
                    //这两句很关键。按钮在Canvas中的定位与它自己的Left以及Top不是一个概念
                    

                    canvas1.Children.Add(bt);
                    
                    
                }
            }

            
        }


    }
}

1. 现在没有Controls这个概念了,而是有一个Children属性,代表了所有的子内容

2.针对不同的容器,有一些特殊的方法来定位子元素。例如Canvas的SetTop等方法 。

#6


引用 5 楼 gac520 的回复:
首先,在WPF中进行布局控制有几个主要的容器

Canvas是按照绝对位置定位的,很像上面的Panel这种机制;
StackPanel呢,则是基于流模式的,它没有绝对定位的概念,一批控件要么从左到右排列,要么从上而下排列
Grid,可能是用的最多的,它可以提供按照行和列的方式更好地组织控件。而事实上,在Grid里面也可以嵌入Canvas和StackPanel,他们结合可以构造出足够复杂的 ……


SetTop我倒是知道了,但是还是和Panel内用dock属性填充有区别的吧,因为主界面是可以调整大小的,用Dock属性设置成Top的话,控件会随着界面拉伸而变长的

#7


引用 3 楼 slowhand 的回复:
在自己的代码中截的一段。和winform里没多少区别啊。


C# code
?



123456789

      Image imageBottomIcon = new Image();       try      {         imageBottomIcon.Source = new BitmapImage(new Uri(System.Windows.For……


这个能随着界面拉伸让控件也跟着拉伸吗?

#8


"现在没有Controls这个概念了"? 是指WPF中没有Controls概念吗?

#9


引用 8 楼 linuxca 的回复:
"现在没有Controls这个概念了"? 是指WPF中没有Controls概念吗?


对啊,以前添加控件都是  
容器.Controls.Add(XX);
然后
xx.Dock=DockStyle.Top;

这样一写就完事了,能自动随容器变大变小,WPF实现这两句代码的功能貌似需要写很多

#10


你可以用StackPanel,连Dock,都不用设置,效果和WinForm设置DockTop是一样的

#11


引用 10 楼 assky124 的回复:
你可以用StackPanel,连Dock,都不用设置,效果和WinForm设置DockTop是一样的


但是这个有可能会横着填充吧?如果一行能容下两个控件的话,他就横着填充了吧?

我这只要竖着的

#12


你MSDN上看看StackPanel,是怎么解释的。有些东西不能自己武断猜测

#13


写个自定义控件 需要的时候添加上去 

#14


不要把添加控件和容器的布局相混淆,wpf添加控件可以使用绑定实现也可以使用传统的winform形式(还是有些区别的)

#15


用StackPanel
代码只要StackPanel.Children.Add(XX)就能实现你要的吧.

#16


我代码在公司呢,有必要的话给你发过去。
大概的方法是在wrappannel上面上新建viewbox:viewbox view=new viewbox();
再新建控件:控件 控件1=new 控件();
view.child=控件1;
每一个想要添加的控件都要对应一个viewbox,然后把viewbox一次排列即可。

#17


5楼应该是对的。

#1


这个问题,一言难尽,先看个这个简单的例子看看对你有帮助没
绑定

#2


引用 1 楼 yysyangyangyangshan 的回复:
这个问题,一言难尽,先看个这个简单的例子看看对你有帮助没
绑定


有那么复杂吗?在winform里是一件很简单的事啊

就是动态向一个容器添加许多控件的代码要怎么写

#3


在自己的代码中截的一段。和winform里没多少区别啊。

      Image imageBottomIcon = new Image();
      try
      {
        imageBottomIcon.Source = new BitmapImage(new Uri(System.Windows.Forms.Application.StartupPath + "\\skins\\bottomIcon.png"));//90*146
      }
      catch { }
      gridBottom.Children.Add(imageBottomIcon);
      Grid.SetColumn(imageBottomIcon, Grid.GetColumn(imageBottomRight));

#4


WPF里面也有容器控件啊,差不多的呀!!!

#5


首先,在WPF中进行布局控制有几个主要的容器

Canvas是按照绝对位置定位的,很像上面的Panel这种机制;
StackPanel呢,则是基于流模式的,它没有绝对定位的概念,一批控件要么从左到右排列,要么从上而下排列
Grid,可能是用的最多的,它可以提供按照行和列的方式更好地组织控件。而事实上,在Grid里面也可以嵌入Canvas和StackPanel,他们结合可以构造出足够复杂的 界面。
第一部分是XAML代码

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="我的扫雷程序" Height="516" Width="592">
    <Grid>
        <Button Height="23" HorizontalAlignment="Left" Margin="20,12,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click">初级</Button>
        <Button Height="23" HorizontalAlignment="Left" Margin="101,12,0,0" Name="button2" VerticalAlignment="Top" Width="75" Click="button2_Click">高级</Button>
        <Canvas Margin="20,41,12,12" Name="canvas1"  />
    </Grid>
</Window>

using System.Windows;
using System.Windows.Controls;

namespace WpfApplication1
{
    /// <summary>
    /// Window1.xaml 的交互逻辑
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            CreateButton(6, 6);
        }


        private void button2_Click(object sender, RoutedEventArgs e)
        {
            CreateButton(9, 9);
        }

        private void CreateButton(int x, int y)
        {
            


            canvas1.Children.Clear();

            //四个方向的边距都是5
            double width = (this.canvas1.ActualWidth - (x + 1) * 5) / x;
            double height = (this.canvas1.ActualHeight - (y + 1) * 5) / y;




            for (int i = 0; i < x; i++)
            {
                for (int j = 0; j < y; j++)
                {
                    Button bt = new Button()
                    {
                        Width = width,
                        Height = height
                    };

                    Canvas.SetTop(bt, j * height + 5);
                    Canvas.SetLeft(bt, i * width + 5);
                    //这两句很关键。按钮在Canvas中的定位与它自己的Left以及Top不是一个概念
                    

                    canvas1.Children.Add(bt);
                    
                    
                }
            }

            
        }


    }
}

1. 现在没有Controls这个概念了,而是有一个Children属性,代表了所有的子内容

2.针对不同的容器,有一些特殊的方法来定位子元素。例如Canvas的SetTop等方法 。

#6


引用 5 楼 gac520 的回复:
首先,在WPF中进行布局控制有几个主要的容器

Canvas是按照绝对位置定位的,很像上面的Panel这种机制;
StackPanel呢,则是基于流模式的,它没有绝对定位的概念,一批控件要么从左到右排列,要么从上而下排列
Grid,可能是用的最多的,它可以提供按照行和列的方式更好地组织控件。而事实上,在Grid里面也可以嵌入Canvas和StackPanel,他们结合可以构造出足够复杂的 ……


SetTop我倒是知道了,但是还是和Panel内用dock属性填充有区别的吧,因为主界面是可以调整大小的,用Dock属性设置成Top的话,控件会随着界面拉伸而变长的

#7


引用 3 楼 slowhand 的回复:
在自己的代码中截的一段。和winform里没多少区别啊。


C# code
?



123456789

      Image imageBottomIcon = new Image();       try      {         imageBottomIcon.Source = new BitmapImage(new Uri(System.Windows.For……


这个能随着界面拉伸让控件也跟着拉伸吗?

#8


"现在没有Controls这个概念了"? 是指WPF中没有Controls概念吗?

#9


引用 8 楼 linuxca 的回复:
"现在没有Controls这个概念了"? 是指WPF中没有Controls概念吗?


对啊,以前添加控件都是  
容器.Controls.Add(XX);
然后
xx.Dock=DockStyle.Top;

这样一写就完事了,能自动随容器变大变小,WPF实现这两句代码的功能貌似需要写很多

#10


你可以用StackPanel,连Dock,都不用设置,效果和WinForm设置DockTop是一样的

#11


引用 10 楼 assky124 的回复:
你可以用StackPanel,连Dock,都不用设置,效果和WinForm设置DockTop是一样的


但是这个有可能会横着填充吧?如果一行能容下两个控件的话,他就横着填充了吧?

我这只要竖着的

#12


你MSDN上看看StackPanel,是怎么解释的。有些东西不能自己武断猜测

#13


写个自定义控件 需要的时候添加上去 

#14


不要把添加控件和容器的布局相混淆,wpf添加控件可以使用绑定实现也可以使用传统的winform形式(还是有些区别的)

#15


用StackPanel
代码只要StackPanel.Children.Add(XX)就能实现你要的吧.

#16


我代码在公司呢,有必要的话给你发过去。
大概的方法是在wrappannel上面上新建viewbox:viewbox view=new viewbox();
再新建控件:控件 控件1=new 控件();
view.child=控件1;
每一个想要添加的控件都要对应一个viewbox,然后把viewbox一次排列即可。

#17


5楼应该是对的。