I have the following code which creates WPF controls and then adds them to a window in a fashion I need. It works decently, but when trying to create 256 (x4 - two textblocks, combo box, textbox) controls it takes a while to display the tab. 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.
我有以下代码创建WPF控件,然后以我需要的方式将它们添加到窗口。它运行得很好,但是当尝试创建256(x4 - 两个文本块,组合框,文本框)控件时,显示选项卡需要一段时间。窗口加载很好但我有很多选项卡,当我点击点设置选项卡时,它在显示选项卡之前稍微滞后。它只在我第一次点击选项卡时滞后,每次在第一次立即响应之后。
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 个解决方案
#1
0
- 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).
- You can set the points List size during creation to 256, this will prevent memory allocations during the items adding operation.
- Consider use a StringBuilder if Global.currentZonesToMap is large.
- Use StringBuilder to build the value for the DevicePoint.desc string property.
如果您的计算机有多个核心,并且我假设它有,请尝试并行执行for循环(parallelfor(来自.net 4或更高版本)。
您可以将创建期间的列表大小设置为256,这将阻止在项目添加操作期间进行内存分配。
如果Global.currentZonesToMap很大,请考虑使用StringBuilder。
使用StringBuilder为DevicePoint.desc字符串属性构建值。
Good luck,
M. Moshe
#1
0
- 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).
- You can set the points List size during creation to 256, this will prevent memory allocations during the items adding operation.
- Consider use a StringBuilder if Global.currentZonesToMap is large.
- Use StringBuilder to build the value for the DevicePoint.desc string property.
如果您的计算机有多个核心,并且我假设它有,请尝试并行执行for循环(parallelfor(来自.net 4或更高版本)。
您可以将创建期间的列表大小设置为256,这将阻止在项目添加操作期间进行内存分配。
如果Global.currentZonesToMap很大,请考虑使用StringBuilder。
使用StringBuilder为DevicePoint.desc字符串属性构建值。
Good luck,
M. Moshe