I’m working on a WPF application with a tabbed MDI interface. Basically, the user clicks a menu item and this creates and adds a new tab. A new 'MyUserControl' is created and set to be the tab's Content. Something like this:
private void MenuItem_OnClick(object sender, RoutedEventArgs e)
{
this.TabControl.Items.Add(new TabItem() { Content = new MyUserControl() });
}
MyUserControl is composed of several nested controls (approx. 8 controls). When this appr开发者_开发技巧oach is wired up to the actual control, the performance is unacceptable.
Unless I’m losing my mind, I’ve noticed that the performance hit seems to be much less when declaring the tab and content in xaml ahead of time and simply toggling the tab item's Visibility property:
<Controls:TabControl x:Name="TabControl" Grid.Row="1">
<Controls:TabControl.Items>
<Controls:TabItem x:Name="MyTabItem" Visibility="Collapsed">
<Controls:MyUserControl x:Name="MyUserControl" />
</Controls:TabItem>
</Controls:TabControl.Items>
</Controls:TabControl>
and
private void MenuItem_OnClick(object sender, RoutedEventArgs e)
{
this.MyTabItem.Visibility = Visibility.Visible;
}
Can anyone explain this? Is it really more efficient to build the "visual tree" in xaml rather than programmatically? Or has the performance hit in my second approach just been moved to the overall form's load instead of when the menu item is clicked as in the first approach?
The second approach definitely seems to perform much better. Any thoughts?
It is no more efficient to declare it it xaml. I think you are correct in thinking that the performance hit has been moved to the form load.
If it is taking too long to load, maybe it is doing too much work in its constructor. See if you can minimize the work done during the loading of the control.
Otherwise, if the problem is just the sheer amount of controls in the user control, maybe you could keep a fully loaded tab in memory until it is ready to be used. Once the user clicks the menu item, add it to the tabcontrol and then start loading a new one in a background thread.
Yes, you moved the performance hit to the initialization of the Window. Even collapsed, the instance of the UserControl
has been made - you've added it explicitly to the TabControl
. Opening a tag in xaml is the same thing as saying new
. Collapsed controls have to be constructed because even if you can't see it or interact with it on screen, other controls can have bindings to it and code-behind can work with the instance.
If you prefer your first approach, try caching the instance of the UserControl
if you can instead of creating a new one each time.
精彩评论