一个窗口中有25个WPF日历,需要5秒才能打开Window

时间:2013-08-30 20:12:00

标签: c# wpf performance xaml calendar

我是WPF的新手,并试图了解它可能会有多慢。我在Visual Studio 2010(.NET 4)中启动了一个新的WPF应用程序,并创建了这个XAML:

<Window x:Class="CalendarTest1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="800" Width="1000">
    <WrapPanel>
        <Calendar />
        <Calendar />
        <Calendar />
...repeats for a total of 25 calendar objects...
    </WrapPanel>
</Window>

当我运行我的应用程序时,无论是否在IDE中,窗口打开需要5秒钟。一旦打开,它会快速重绘(当我调整大小时),一切看起来都很活泼。

我的电脑不是最快的:AMD双核2.3GHz,2GB内存,XP 32位操作系统,板载视频。

我可以放置25个按钮,而不是日历,并且可以在不到1秒的时间内加载。

我正在尝试在MS Outlook日历中创建日视图中的小月历,如下所示:

enter image description here

所以我想我可以使用WrapPanel并在调整大小时添加/删除Calendar控件。我可能不需要25,但即使有9或12它比我想象的慢(我有一个遗留的Win32应用程序,在不到1秒的时间内显示18个这样的日历)。

我的问题是:

由于某种设计,日历控件是否会变慢 - 或者设计不好,或者仅仅是为此用途而设计,还是因为它试图显示大量数据/控件/信息而变慢?

如果我去创建自己的控件,假设我使用了一个好的设计(一般的想法欢迎),它可以更快,或者这只是WPF的“典型”吗?

我可以做些什么来使这种用法的默认日历控件更快?

3 个答案:

答案 0 :(得分:6)

本身不是答案,但是将其添加到Window.Resources会使我的机器的加载时间减少50%(25个日历现在不到1秒)

    <Window.Resources>
        <Style TargetType="CalendarDayButton">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="CalendarDayButton">
                        <ContentPresenter ContentSource="Content" Margin="2"/>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

        <Style TargetType="Calendar">
            <Setter Property="CalendarDayButtonStyle" Value="{StaticResource {x:Type CalendarDayButton}}"/>
        </Style>
    </Window.Resources>

修改

此视觉更改不会影响控件的功能。所有日历日项目仍为Selectable,您可以绑定Calendar.SelectedDate属性。

没有视觉指示选择了某个项目,因此点击日期似乎什么都不做。

只需将其添加到ControlTemplate:

                <ControlTemplate TargetType="CalendarDayButton">
                    <ContentPresenter ContentSource="Content" Margin="2"/>

                    <ControlTemplate.Triggers>
                        <!-- Set The FontWeight to "Bold" when Selected -->
                        <Trigger Property="IsSelected" Value="True">
                            <Setter Property="FontWeight" Value="Bold"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>

您可以使用此ControlTemplate及其Triggers来添加视觉效果。虽然记住模板越复杂,但加载时间越长。

答案 1 :(得分:3)

这将让您了解日历 与使用Snoop的按钮的对比。是的,我们确实希望很多日历可以花费更多的渲染时间。如果你需要使用它们中的很多,我会尝试创建你自己的更简单和/或虚拟化它们

一个按钮,3个孩子......

enter image description here

还有一本日历,522个孩子。请注意,我没有展开的每个CalendarButtons仍然有9个孩子

enter image description here enter image description here

答案 2 :(得分:0)

我会更新这个,因为我有时间完成这个新控件,但到目前为止,我向自己证明了我可以在窗口中拥有大量控件并且仍然可以快速加载。在这种情况下,1050个TextBlocks(7列* 6行* 25个我的用户控件实例),我的窗口加载时间不到1秒。

到目前为止,这是我的简单用户控件:

<UserControl x:Class="FastCalendar.UserControl1"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:FastCalendar"
             xmlns:vm="clr-namespace:FastCalendar.ViewModels"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300" Margin="5">
    <UserControl.Resources>
        <vm:MainViewModel x:Key="ViewModel" />
    </UserControl.Resources>
    <ItemsControl Width="180" Height="170" ItemsSource="{Binding Path=Days, Source={StaticResource ViewModel}}">
        <ItemsControl.ItemContainerStyle>
            <Style>
                <Setter Property="Grid.Row" Value="{Binding Path=Row}" />
                <Setter Property="Grid.Column" Value="{Binding Path=Column}" />
            </Style>
        </ItemsControl.ItemContainerStyle>

        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" Text="{Binding Path=Day}" />
            </DataTemplate>
        </ItemsControl.ItemTemplate>

        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Grid ShowGridLines="True">
                    <Grid.RowDefinitions>
                        <RowDefinition />
                        <RowDefinition />
                        <RowDefinition />
                        <RowDefinition />
                        <RowDefinition />
                        <RowDefinition />
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition />
                        <ColumnDefinition />
                        <ColumnDefinition />
                        <ColumnDefinition />
                        <ColumnDefinition />
                        <ColumnDefinition />
                        <ColumnDefinition />
                    </Grid.ColumnDefinitions>
                </Grid>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>

    </ItemsControl>
</UserControl>

我将其中的25个放入WrapPanel中,并在不到1秒的时间内加载。我仍然需要为我的用户控件添加更多控件和样式,但我认为它仍然比内置Calendar控件快得多(我希望)。

.-即使在窗口上有50份我的用户控件,它也会在大约1秒内加载。