项目: 我有一个父面板,它包含一个ComboBox和FlowLayoutPanel。 FlowLayoutPanel包含可变数量的子面板(从UserControl继承的自定义控件)。每个子面板包含一些标签,两个ComboBox,一个按钮和一个带有3个ComboBox列和一个按钮列的DataGridView。 DataGridView可能有1-6行。从父面板上的ComboBox中选择项目时,FlowLayoutPanel将填充子面板。
问题: 使用大约50个子面板填充FlowLayoutPanel大约需要2.5秒。具体来说,我已经确定调用FlowLayoutPanel.Controls.AddRange()是罪魁祸首。
相关代码:我不能在这里发布我的所有代码(代码太多,部分内容是保密的),但我会尽力解释发生了什么。
家长小组:
private void displayInformation(Suite suite)
{
this.SuspendLayout();
// Get dependencies.
List<SuiteRange> dependents = new List<SuiteRange>(suite.dependencies.Keys);
dependents.Sort(SuiteRange.Compare);
// Create a ChildPanel for each dependent.
List<ChildPanel> rangePanels = new List<ChildPanel>();
foreach (SuiteRange dependent in dependents)
{
ChildPanel sdp = new ChildPanel();
sdp.initialize(initialSuite.name, dataAccess);
sdp.displayInformation(dependent, suite.dependencies[dependent]);
rangePanels.Add(sdp);
}
// Put the child panels in the FlowLayoutPanel.
flpDependencyGroups.SuspendLayout();
// Takes ~2.5 seconds
flpDependencyGroups.Controls.AddRange(rangePanels.ToArray());
flpDependencyGroups.ResumeLayout();
// Takes ~0.5 seconds
updateChildPanelSizes();
this.ResumeLayout();
}
我尝试过的事情:
可能相关的事情:
编辑:解决方案:
@ HighCore的答案是正确的解决方案。不幸的是,我现在不会实现它(它可能会发生在路上),因为我找到了一个解决方法。解决方法并没有真正解决问题,只是掩盖它,因此我不会将此作为答案发布。我发现,如果“依赖关系”选项卡不在顶部(即选择了“产品列表”选项卡),则表单会加载一半的时间。这将加载时间减少到约1秒,这是可以接受的。当正在加载数据并且Dependencies选项卡位于顶部时,我切换到Product Lists选项卡,在选项卡控件上方抛出一个深灰色框,中间显示“Loading ...”,加载数据,然后切换回到Dependencies选项卡。
感谢大家的意见和建议,非常感谢。
答案 0 :(得分:4)
发布此答案是因为OP要求:
这就是你在WPF中做类似的事情:
<UserControl x:Class="WpfApplication7.ListBoxSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<DockPanel>
<Button Content="Load" Click="Load_Click" DockPanel.Dock="Top"/>
<ListBox ItemsSource="{Binding}"
HorizontalContentAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderBrush="LightGray" BorderThickness="1" Padding="5"
Background="#FFFAFAFA">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="Dependent Versions" FontWeight="Bold"
Grid.ColumnSpan="2" HorizontalAlignment="Center"/>
<TextBlock Text="From:" FontWeight="Bold"
Grid.Row="1" HorizontalAlignment="Center"/>
<TextBlock Text="To (exclusive):" FontWeight="Bold"
Grid.Row="1" Grid.Column="1" HorizontalAlignment="Center"/>
<ComboBox SelectedItem="{Binding From}"
ItemsSource="{Binding FromOptions}"
Grid.Row="2" Margin="5"/>
<ComboBox SelectedItem="{Binding To}"
ItemsSource="{Binding ToOptions}"
Grid.Row="2" Grid.Column="1" Margin="5"/>
<DataGrid ItemsSource="{Binding ChildItems}"
AutoGenerateColumns="False" CanUserAddRows="False"
Grid.Column="2" Grid.RowSpan="4">
<DataGrid.Columns>
<DataGridTextColumn Header="XXXX" Binding="{Binding XXXX}"/>
<DataGridTextColumn Header="Dependee From" Binding="{Binding DependeeFrom}"/>
<DataGridTextColumn Header="Dependee To" Binding="{Binding DependeeTo}"/>
<DataGridTemplateColumn Width="25">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Content="X"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
<Button Content="Delete"
Grid.Column="3"
HorizontalAlignment="Right" VerticalAlignment="Top"/>
</Grid>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DockPanel>
</UserControl>
Code Behind(仅支持示例的样板)
public partial class ListBoxSample : UserControl
{
public ListBoxSample()
{
InitializeComponent();
}
public void LoadData()
{
Task.Factory.StartNew(() =>
{
var list = new List<DataItem>();
for (int i = 0; i < 100000; i++)
{
var item = new DataItem()
{
From = "1",
To = "2",
ChildItems =
{
new ChildItem()
{
DependeeFrom = i.ToString(),
DependeeTo = (i + 10).ToString(),
XXXX = "XXXX"
},
new ChildItem()
{
DependeeFrom = i.ToString(),
DependeeTo = (i + 10).ToString(),
XXXX = "XXXX"
},
new ChildItem()
{
DependeeFrom = i.ToString(),
DependeeTo = (i + 10).ToString(),
XXXX = "XXXX"
}
}
};
list.Add(item);
}
return list;
}).ContinueWith(t =>
{
Dispatcher.Invoke((Action) (() => DataContext = t.Result));
});
}
private void Load_Click(object sender, System.Windows.RoutedEventArgs e)
{
LoadData();
}
}
数据项:
public class DataItem
{
public List<ChildItem> ChildItems { get; set; }
public List<string> FromOptions { get; set; }
public List<string> ToOptions { get; set; }
public string From { get; set; }
public string To { get; set; }
public DataItem()
{
ChildItems = new List<ChildItem>();
FromOptions = Enumerable.Range(0,10).Select(x => x.ToString()).ToList();
ToOptions = Enumerable.Range(0, 10).Select(x => x.ToString()).ToList();
}
}
public class ChildItem
{
public string XXXX { get; set; }
public string DependeeFrom { get; set; }
public string DependeeTo { get; set; }
}
然后使用ElementHost
:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
var elementHost = new ElementHost
{
Dock = DockStyle.Fill,
Child = new ListBoxSample()
};
Controls.Add(elementHost);
}
}
结果:
DataGrid
拉伸到剩余空间来进一步自定义它。见WPF Layouts。PresentationCore.dll
,PresentationFramework.dll
,WindowsBase.dll
,System.Xaml.dll
和WindowsFormsIntegration.dll
,所有这些都属于.Net框架本身(无方)