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

本文关键字:控件 速度 添加 UI 何提高 | 更新日期: 2023-09-27 18:21:52

我有以下代码,它创建WPF控件,然后以我需要的方式将它们添加到窗口中。它工作得很好,但当试图创建256(x4-两个文本块、组合框、文本框)控件时,需要一段时间才能显示选项卡。窗口加载良好,但我有很多选项卡,当我点击点设置选项卡时,它在显示选项卡之前会滞后一点。它只在我第一次点击选项卡时滞后,每次点击后都会立即响应。

一开始我认为这是一个渲染问题,但经过大量其他研究,我觉得C#/WPF在动态创建一堆对象并将它们添加到表单中方面做得不好。

如果我将项目数量减少到50,它会立即响应,100是一个轻微的滞后,200(256)是一个稍大的滞后,太多了,用户无法接受。

以前遇到过类似问题的任何经验,以及如何解决问题的建议或其他技巧。

提前感谢!韦斯利

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

新代码(使用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>

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

  1. 如果您的计算机有多个内核,并且我假设它有,请尝试并行执行for循环(parallel for(来自.net 4或更高版本)
  2. 您可以在创建期间将点列表大小设置为256,这将阻止在项目添加操作期间分配内存
  3. 如果Global.currentZonesToMap较大,请考虑使用StringBuilder
  4. 使用StringBuilder生成DevicePoint.desc字符串属性的值

祝你好运,

M。Moshe