简体   繁体   English

如何提高向UI添加控件的速度

[英]How to improve speed of adding controls to UI

I have the following code which creates WPF controls and then adds them to a window in a fashion I need. 我有以下代码创建WPF控件,然后以所需的方式将它们添加到窗口中。 It works decently, but when trying to create 256 (x4 - two textblocks, combo box, textbox) controls it takes a while to display the tab. 它可以正常工作,但是在尝试创建256(x4-两个文本块,组合框,文本框)控件时,需要花费一些时间才能显示选项卡。 Window loads fine but I have many tabs and when I click on point setup tab it lags a little before displaying the tab. 窗口加载正常,但是我有很多选项卡,当我单击“点设置”选项卡时,它在显示选项卡之前滞后了一点。 It only lags the first time I click on the tab, every time after the first it responds immediately. 它仅在我第一次单击选项卡时滞后,每次单击后都会立即响应。

At first I thought it was a rendering issue, but after much other research I am of the impression C#/WPF doesn't do well with creating a bunch of objects on the fly and adding them to forms. 起初我以为这是一个渲染问题,但是经过许多其他研究后,我对C#/ WPF的印象并不理想,因为它无法即时创建一堆对象并将其添加到表单中。

If I drop the number of items to 50 it responds immediately, 100 is a slight lag and 200 (256) is a little more of a lag and too much to be acceptable to users. 如果我将项目数降低到50,它会立即做出响应,100则是一个轻微的滞后,200(256)则是一个稍许的滞后,太高了以至于用户无法接受。

Any experiences with issues like this before and advice for how to fix it or other tips/tricks. 之前遇到过类似问题的任何经验,以及有关如何解决它的建议或其他技巧/窍门。

Thanks in advance! 提前致谢! Wesley 卫斯理

public static void pointSetup(VirtualizingStackPanel desc, VirtualizingStackPanel map) //Draws point description and point map table in point setup tab
    {
        StackPanel row;
        TextBlock text;
        TextBox textBox;
        ComboBox comboBox;

        Thickness rowSpacing = new Thickness(0, 0, 0, 5);
        Thickness textSpacing = new Thickness(0, 3, 5, 3);
        List<string> list = new List<string>();

        list.Add("xx");
        for (byte i = 0; i < Global.currentZonesToMap; i++)
        {
            list.Add("Zone  " + (i + 1));
        }

        for (short i = 0; i < 256; i++)
        {
            //desc
            row = new StackPanel();
            row.Margin = rowSpacing;
            row.Orientation = Orientation.Horizontal;

            text = new TextBlock();
            text.Text = "Point " + (i + 1);
            text.Margin = textSpacing;
            text.Width = 50;

            textBox = new TextBox();
            textBox.MaxLength = 28;
            textBox.Text = "";
            textBox.Width = 270;

            row.Children.Add(text);
            row.Children.Add(textBox);

            desc.Children.Add(row);

            //map
            row = new StackPanel();
            row.Margin = rowSpacing;
            row.Orientation = Orientation.Horizontal;

            text = new TextBlock();
            text.Text = "Point " + (i + 1);
            text.Margin = textSpacing;
            text.Width = 50;

            comboBox = new ComboBox();
            comboBox.ItemsSource = list;
            comboBox.Width = 270;

            row.Children.Add(text);
            row.Children.Add(comboBox);

            map.Children.Add(row);
        }
    }

New Code (using DataTemplate and ItemsControl) 新代码(使用DataTemplate和ItemsControl)

    public class DevicePoint
    {
        public string desc { get; set; }

        public int zone { get; set; }

        public List<string> zones { get; set; }
    }

    //Initialized all variables and displays UI (constructor)
    public Dispatcher()
    {
        InitializeComponent();

        List<string> opts = new List<string>();
        opts.Add("xx");
        for (byte i = 0; i < Global.currentZonesToMap; i++)
        {
            opts.Add("Zone  " + (i + 1));
        }

        List<DevicePoint> points = new List<DevicePoint>();
        for (short i = 0; i < 256; i++)
            points.Add(new DevicePoint() { desc = "Point " + (i + 1), zone = 0, zones = opts });
        pointDesc.ItemsSource = points;
        pointZoneMap.ItemsSource = points;

        ... other stuff here ...
    }

        <StackPanel>
                <TextBlock Margin="10" FontWeight="Bold" HorizontalAlignment="Center" Text="Point Descriptions" />
                <ScrollViewer Width="360" Margin="30,10,30,10" MaxHeight="405">
                    <ItemsControl Name="pointDesc" Margin="5">
                        <ItemsControl.ItemTemplate>
                            <DataTemplate>
                                <StackPanel VirtualizingStackPanel.IsVirtualizing="True" Margin="0,0,0,5" Orientation="Horizontal">
                                    <TextBlock Margin="0,3,5,3" Width="50" Text="{Binding desc}" />
                                    <TextBox MaxLength="28" Width="270" Text="{Binding desc}" />
                                </StackPanel>
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                    </ItemsControl>
                </ScrollViewer>
            </StackPanel>
            <StackPanel Grid.Column="1">
                <TextBlock Margin="10" FontWeight="Bold" HorizontalAlignment="Center" Text="Point - Zone Map" />
                <ScrollViewer Width="360" Margin="30,10,30,10" MaxHeight="405">
                    <ItemsControl Name="pointZoneMap" Margin="5">
                        <ItemsControl.ItemTemplate>
                            <DataTemplate>
                                <StackPanel VirtualizingStackPanel.IsVirtualizing="True" Margin="0,0,0,5" Orientation="Horizontal">
                                    <TextBlock Margin="0,3,5,3" Width="50" Text="{Binding desc}" />
                                    <ComboBox Width="270" ItemsSource="{Binding zones}" SelectedIndex="{Binding zone}" />
                                </StackPanel>
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                    </ItemsControl>
                </ScrollViewer>
            </StackPanel>
  1. If your computer have multiple cores, and I am assuming it have, try to perform the for loop in parallel (parallelfor (from .net 4 or above). 如果您的计算机具有多个核心,并且我假设它具有多个核心,请尝试并行执行for循环(parallelfor(来自.net 4或更高版本)。
  2. You can set the points List size during creation to 256, this will prevent memory allocations during the items adding operation. 您可以将创建期间的点列表大小设置为256,这将防止在项目添加操作期间分配内存。
  3. Consider use a StringBuilder if Global.currentZonesToMap is large. 如果Global.currentZonesToMap大,请考虑使用StringBuilder。
  4. Use StringBuilder to build the value for the DevicePoint.desc string property. 使用StringBuilder生成DevicePoint.desc字符串属性的值。

Good luck, 祝好运,

M. Moshe 莫西

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM